Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@ private Object[] calcFields(IRowMeta rowMeta, Object[] r) throws HopValueExcepti
data.expressionEvaluators[m].setThrownExceptions(new Class<?>[] {Exception.class});
data.expressionEvaluators[m].setParentClassLoader(loader);
data.expressionEvaluators[m].setDefaultImports(functionLib.getImportPackages());
int javaVersion = meta.getEffectiveJavaTargetVersion();
data.expressionEvaluators[m].setTargetVersion(javaVersion);
// Janino default: parse up to Java 11 when source is unset, emit Java 6 bytecode when
// target is unset.
// Keep that permissive parse level for the default target (6) so existing expressions
// keep working.
if (javaVersion > JaninoMeta.JAVA_TARGET_VERSION_MIN) {
data.expressionEvaluators[m].setSourceVersion(javaVersion);
}

// Validate Formula
JaninoCheckerUtil janinoCheckerUtil = new JaninoCheckerUtil();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.apache.hop.ui.core.widget.TableView;
import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
Expand All @@ -50,8 +51,15 @@
public class JaninoDialog extends BaseTransformDialog {
private static final Class<?> PKG = JaninoMeta.class;

private static final String[] JAVA_TARGET_VERSION_ITEMS =
new String[] {
"6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21"
};

private TableView wFields;

private CCombo wJavaTargetVersion;

private final JaninoMeta currentMeta;
private final JaninoMeta originalMeta;

Expand All @@ -75,12 +83,31 @@ public String open() {

changed = currentMeta.hasChanged();

Label wlJavaTargetVersion = new Label(shell, SWT.RIGHT);
wlJavaTargetVersion.setText(
BaseMessages.getString(PKG, "JaninoDialog.JavaTargetVersion.Label"));
PropsUi.setLook(wlJavaTargetVersion);
FormData fdlJavaTargetVersion = new FormData();
fdlJavaTargetVersion.left = new FormAttachment(0, 0);
fdlJavaTargetVersion.right = new FormAttachment(middle, -margin);
fdlJavaTargetVersion.top = new FormAttachment(wSpacer, margin);
wlJavaTargetVersion.setLayoutData(fdlJavaTargetVersion);

wJavaTargetVersion = new CCombo(shell, SWT.BORDER | SWT.READ_ONLY);
PropsUi.setLook(wJavaTargetVersion);
wJavaTargetVersion.setItems(JAVA_TARGET_VERSION_ITEMS);
FormData fdJavaTargetVersion = new FormData();
fdJavaTargetVersion.left = new FormAttachment(middle, 0);
fdJavaTargetVersion.right = new FormAttachment(100, 0);
fdJavaTargetVersion.top = new FormAttachment(wSpacer, margin);
wJavaTargetVersion.setLayoutData(fdJavaTargetVersion);

Label wlFields = new Label(shell, SWT.NONE);
wlFields.setText(BaseMessages.getString(PKG, "JaninoDialog.Fields.Label"));
PropsUi.setLook(wlFields);
FormData fdlFields = new FormData();
fdlFields.left = new FormAttachment(0, 0);
fdlFields.top = new FormAttachment(wSpacer, margin);
fdlFields.top = new FormAttachment(wJavaTargetVersion, margin);
wlFields.setLayoutData(fdlFields);

final int nrFields = currentMeta.getFunctions().size();
Expand Down Expand Up @@ -214,6 +241,14 @@ protected void setComboBoxes() {

/** Copy information from the meta-data currentMeta to the dialog fields. */
public void getData() {
int effectiveVersion = currentMeta.getEffectiveJavaTargetVersion();
int versionIndex = effectiveVersion - JaninoMeta.JAVA_TARGET_VERSION_MIN;
if (versionIndex >= 0 && versionIndex < JAVA_TARGET_VERSION_ITEMS.length) {
wJavaTargetVersion.select(versionIndex);
} else {
wJavaTargetVersion.select(0);
}

if (currentMeta.getFunctions() != null) {
for (int i = 0; i < currentMeta.getFunctions().size(); i++) {
JaninoMetaFunction function = currentMeta.getFunctions().get(i);
Expand Down Expand Up @@ -265,6 +300,9 @@ private void ok() {

transformName = wTransformName.getText(); // return value

currentMeta.setJavaTargetVersion(
Const.toInt(wJavaTargetVersion.getText(), JaninoMeta.JAVA_TARGET_VERSION_DEFAULT));

currentMeta.getFunctions().clear();
for (TableItem item : wFields.getNonEmptyItems()) {
JaninoMetaFunction function = new JaninoMetaFunction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,28 @@
public class JaninoMeta extends BaseTransformMeta<Janino, JaninoData> {
private static final Class<?> PKG = JaninoMeta.class;

/** Default matches Janino bytecode default ({@code UnitCompiler#getDefaultTargetVersion()}). */
public static final int JAVA_TARGET_VERSION_DEFAULT = 6;

public static final int JAVA_TARGET_VERSION_MIN = 6;
public static final int JAVA_TARGET_VERSION_MAX = 21;

/** The formula calculations to be performed */
@HopMetadataProperty(
key = "formula",
injectionGroupKey = "FORMULA",
injectionGroupDescription = "Janino.Injection.FORMULA")
private List<JaninoMetaFunction> functions;

/**
* Java language / class file level passed to Janino ({@link
* org.codehaus.janino.ExpressionEvaluator #setSourceVersion} and {@link
* org.codehaus.janino.ExpressionEvaluator#setTargetVersion}). When unset or invalid, {@link
* #JAVA_TARGET_VERSION_DEFAULT} is used.
*/
@HopMetadataProperty(key = "java_target_version")
private int javaTargetVersion = JAVA_TARGET_VERSION_DEFAULT;

public JaninoMeta() {
super();
this.functions = new ArrayList<>();
Expand All @@ -64,6 +79,19 @@ public JaninoMeta() {
public JaninoMeta(JaninoMeta m) {
this();
m.functions.forEach(f -> this.functions.add(new JaninoMetaFunction(f)));
this.javaTargetVersion = m.javaTargetVersion;
}

/**
* Resolved Janino compiler source/target version (major Java version number), for backwards
* compatibility when pipelines omit {@link #javaTargetVersion} or contain invalid values.
*/
public int getEffectiveJavaTargetVersion() {
if (javaTargetVersion < JAVA_TARGET_VERSION_MIN
|| javaTargetVersion > JAVA_TARGET_VERSION_MAX) {
return JAVA_TARGET_VERSION_DEFAULT;
}
return javaTargetVersion;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.plugins.IPlugin;
import org.apache.hop.core.plugins.PluginRegistry;
Expand Down Expand Up @@ -175,7 +176,16 @@ public Set<Class<?>> findAllClassesUsingGoogleGuice(ClassLoader classLoader, Str
throws IOException {
return ClassPath.from(classLoader).getAllClasses().stream()
.filter(clazz -> clazz.getPackageName().contains(packageName))
.map(ClassPath.ClassInfo::load)
.flatMap(
clazz -> {
try {
return Stream.of(clazz.load());
} catch (Exception | Error e) {
// Skip classes that cannot be loaded (e.g. bad path-based class names from
// test-classpath entries, missing dependencies, incompatible bytecode).
return Stream.empty();
}
})
.collect(Collectors.toSet());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.apache.hop.pipeline.PipelineHopMeta;
import org.apache.hop.pipeline.PipelineMeta;
import org.apache.hop.pipeline.transform.TransformMeta;
import org.apache.hop.pipeline.transforms.janino.JaninoMeta;
import org.apache.hop.pipeline.transforms.rowgenerator.GeneratorField;
import org.apache.hop.pipeline.transforms.rowgenerator.RowGeneratorMeta;
import org.apache.hop.pipeline.transforms.userdefinedjavaclass.UserDefinedJavaClassCodeSnippets.Category;
Expand All @@ -66,6 +67,7 @@
import org.apache.hop.ui.util.EnvironmentUtils;
import org.apache.hop.ui.util.SwtSvgImageUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabFolder2Adapter;
import org.eclipse.swt.custom.CTabFolderEvent;
Expand Down Expand Up @@ -108,10 +110,17 @@ public class UserDefinedJavaClassDialog extends BaseTransformDialog {
public static final String CONST_SET_VALUE = "setValue()";
public static final String CONST_SNIPPITS_CATEGORY = "Snippits Category";

private static final String[] JAVA_TARGET_VERSION_ITEMS =
new String[] {
"6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21"
};

private ModifyListener lsMod;

private TableView wFields;

private CCombo wJavaTargetVersion;

private Label wlPosition;

private Button wClearResultFields;
Expand Down Expand Up @@ -224,6 +233,28 @@ public String open() {

Control lastControl = wSpacer;

Label wlJavaTargetVersion = new Label(shell, SWT.RIGHT);
wlJavaTargetVersion.setText(
BaseMessages.getString(PKG, "UserDefinedJavaClassDialog.JavaTargetVersion.Label"));
PropsUi.setLook(wlJavaTargetVersion);
FormData fdlJavaTargetVersion = new FormData();
fdlJavaTargetVersion.left = new FormAttachment(0, 0);
fdlJavaTargetVersion.right = new FormAttachment(middle, -margin);
fdlJavaTargetVersion.top = new FormAttachment(lastControl, margin);
wlJavaTargetVersion.setLayoutData(fdlJavaTargetVersion);

wJavaTargetVersion = new CCombo(shell, SWT.BORDER | SWT.READ_ONLY);
PropsUi.setLook(wJavaTargetVersion);
wJavaTargetVersion.setItems(JAVA_TARGET_VERSION_ITEMS);
wJavaTargetVersion.addModifyListener(lsMod);
FormData fdJavaTargetVersion = new FormData();
fdJavaTargetVersion.left = new FormAttachment(middle, 0);
fdJavaTargetVersion.right = new FormAttachment(100, 0);
fdJavaTargetVersion.top = new FormAttachment(lastControl, margin);
wJavaTargetVersion.setLayoutData(fdJavaTargetVersion);

lastControl = wJavaTargetVersion;

SashForm wSash = new SashForm(shell, SWT.VERTICAL);

// Top sash form
Expand Down Expand Up @@ -1027,6 +1058,8 @@ public void getData() {

wClearResultFields.setSelection(input.isClearingResultFields());

wJavaTargetVersion.setText(Integer.toString(input.getEffectiveJavaTargetVersion()));

wFields.setRowNums();
wFields.optWidth(true);

Expand Down Expand Up @@ -1118,6 +1151,9 @@ private boolean cancel() {
}

private void getInfo(UserDefinedJavaClassMeta meta) {
meta.setJavaTargetVersion(
Const.toInt(wJavaTargetVersion.getText(), JaninoMeta.JAVA_TARGET_VERSION_DEFAULT));

int nrFields = wFields.nrNonEmpty();
List<FieldInfo> newFields = new ArrayList<>(nrFields);
for (int i = 0; i < nrFields; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.apache.hop.core.CheckResult;
Expand All @@ -46,6 +47,7 @@
import org.apache.hop.pipeline.transform.BaseTransformMeta;
import org.apache.hop.pipeline.transform.ITransformIOMeta;
import org.apache.hop.pipeline.transform.TransformMeta;
import org.apache.hop.pipeline.transforms.janino.JaninoMeta;
import org.apache.hop.pipeline.transforms.util.JaninoCheckerUtil;
import org.codehaus.commons.compiler.CompileException;
import org.codehaus.janino.ClassBodyEvaluator;
Expand Down Expand Up @@ -181,6 +183,34 @@ public Object clone() throws CloneNotSupportedException {
injectionGroupDescription = "UserDefinedJavaClass.Injection.PARAMETERS")
private List<UsageParameter> usageParameters;

/**
* Janino bytecode / language level for compiling embedded user classes (same semantics as {@link
* JaninoMeta#getEffectiveJavaTargetVersion()}).
*/
@Getter
@Setter(AccessLevel.NONE)
@HopMetadataProperty(key = "java_target_version")
private int javaTargetVersion = JaninoMeta.JAVA_TARGET_VERSION_DEFAULT;

public void setJavaTargetVersion(int javaTargetVersion) {
if (this.javaTargetVersion != javaTargetVersion) {
this.javaTargetVersion = javaTargetVersion;
this.hasChanged = true;
}
}

/**
* Resolved Janino compiler source/target version for {@link ClassBodyEvaluator}, for backwards
* compatibility when pipelines omit {@link #javaTargetVersion} or contain invalid values.
*/
public int getEffectiveJavaTargetVersion() {
if (javaTargetVersion < JaninoMeta.JAVA_TARGET_VERSION_MIN
|| javaTargetVersion > JaninoMeta.JAVA_TARGET_VERSION_MAX) {
return JaninoMeta.JAVA_TARGET_VERSION_DEFAULT;
}
return javaTargetVersion;
}

public UserDefinedJavaClassMeta() {
super();
hasChanged = true;
Expand All @@ -201,14 +231,15 @@ public UserDefinedJavaClassMeta(UserDefinedJavaClassMeta m) {
m.targetTransformDefinitions.forEach(
d -> this.targetTransformDefinitions.add(new TargetTransformDefinition(d)));
m.usageParameters.forEach(u -> this.usageParameters.add(new UsageParameter(u)));
this.javaTargetVersion = m.javaTargetVersion;
}

@VisibleForTesting
Class<?> cookClass(UserDefinedJavaClassDef def, ClassLoader clsLoader)
throws CompileException, IOException, HopTransformException {

String checksum = def.getChecksum();
Class<?> rtn = UserDefinedJavaClassMeta.CLASS_CACHE.getIfPresent(checksum);
String cacheKey = def.getChecksum() + ":" + getEffectiveJavaTargetVersion();
Class<?> rtn = UserDefinedJavaClassMeta.CLASS_CACHE.getIfPresent(cacheKey);
if (rtn != null) {
return rtn;
}
Expand Down Expand Up @@ -247,9 +278,15 @@ Class<?> cookClass(UserDefinedJavaClassDef def, ClassLoader clsLoader)
"org.apache.hop.core.variables.*",
"java.util.*");

int javaVersion = getEffectiveJavaTargetVersion();
cbe.setTargetVersion(javaVersion);
if (javaVersion > JaninoMeta.JAVA_TARGET_VERSION_MIN) {
cbe.setSourceVersion(javaVersion);
}

cbe.cook(new Scanner(null, sr));
rtn = cbe.getClazz();
UserDefinedJavaClassMeta.CLASS_CACHE.put(checksum, rtn);
UserDefinedJavaClassMeta.CLASS_CACHE.put(cacheKey, rtn);
return rtn;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Janino.Injection.VALUE_PRECISION=Precision
Janino.Injection.VALUE_TYPE=Type
Janino.Name=User defined Java expression
JaninoDialog.DialogTitle=User defined Java expression
JaninoDialog.JavaTargetVersion.Label=Java target version:
JaninoDialog.Fields.Label=Fields:
JaninoDialog.Janino.Column=Java expression
JaninoDialog.Length.Column=Length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ UserDefinedJavaClassDialog.GettingFields.Label=Getting fields...please wait
UserDefinedJavaClassDialog.InfoFields.Label=Info fields
UserDefinedJavaClassDialog.InfoTransforms.Label=Info transforms\:
UserDefinedJavaClassDialog.InputFields.Label=Input fields
UserDefinedJavaClassDialog.JavaTargetVersion.Label=Java target version\:
UserDefinedJavaClassDialog.NoTransformClassSet=No class tab has been set as the transform class\! Should the first tab set as active Script?
UserDefinedJavaClassDialog.OutputFields.Label=Output fields
UserDefinedJavaClassDialog.Parameters.Label=Parameters\:
Expand Down
Loading
Loading