| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openjpa.lib.ant; |
| |
| import java.io.File; |
| import java.security.AccessController; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.openjpa.lib.conf.Configuration; |
| import org.apache.openjpa.lib.conf.ConfigurationImpl; |
| import org.apache.openjpa.lib.conf.ConfigurationProvider; |
| import org.apache.openjpa.lib.conf.Configurations; |
| import org.apache.openjpa.lib.conf.ProductDerivations; |
| import org.apache.openjpa.lib.util.J2DoPrivHelper; |
| import org.apache.openjpa.lib.util.Localizer; |
| import org.apache.openjpa.lib.util.MultiClassLoader; |
| import org.apache.openjpa.lib.util.StringUtil; |
| import org.apache.tools.ant.AntClassLoader; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.DirectoryScanner; |
| import org.apache.tools.ant.taskdefs.MatchingTask; |
| import org.apache.tools.ant.types.FileSet; |
| import org.apache.tools.ant.types.Path; |
| |
| /** |
| * Ant tasks all have a nested <code><config&rt;</code> tag, which uses |
| * the configuration as a bean-like task. E.g., you can do: |
| * |
| * <code> |
| * <mytask&rt;<br /> |
| * <config connectionUserName="foo"/&rt;<br /> |
| * </mytask&rt; |
| * </code> |
| * |
| * The default configuration for the system will be used if the |
| * <code><config&rt;</code> subtask is excluded. |
| * |
| */ |
| public abstract class AbstractTask extends MatchingTask { |
| |
| private static final Localizer _loc = Localizer.forPackage |
| (AbstractTask.class); |
| |
| protected final List<FileSet> fileSets = new ArrayList<>(); |
| protected boolean haltOnError = true; |
| protected Path classpath = null; |
| protected boolean useParent = false; |
| protected boolean isolate = false; |
| |
| private ConfigurationImpl _conf = null; |
| private AntClassLoader _cl = null; |
| |
| /** |
| * Set whether we want the task to ignore all errors. |
| */ |
| public void setHaltOnError(boolean haltOnError) { |
| this.haltOnError = haltOnError; |
| } |
| |
| /** |
| * Whether we want the ClassLoader to be isolated from |
| * all other ClassLoaders |
| */ |
| public void setIsolate(boolean isolate) { |
| this.isolate = isolate; |
| } |
| |
| /** |
| * Whether we want to delegate to the parent ClassLoader |
| * for resolveing classes. This may "taint" classes. |
| */ |
| public void setUseParentClassloader(boolean useParent) { |
| this.useParent = useParent; |
| } |
| |
| /** |
| * The task configuration. |
| */ |
| public Configuration getConfiguration() { |
| if (_conf == null) { |
| _conf = newConfiguration(); |
| _conf.setDeferResourceLoading(true); |
| } |
| return _conf; |
| } |
| |
| /** |
| * Implement this method to return a configuration object for the |
| * product in use. |
| */ |
| protected abstract ConfigurationImpl newConfiguration(); |
| |
| /** |
| * Perform the task action on the given files. |
| */ |
| protected abstract void executeOn(String[] files) throws Exception; |
| |
| /** |
| * Return the classloader to use. |
| */ |
| protected ClassLoader getClassLoader() { |
| if (_cl != null) |
| return _cl; |
| |
| if (classpath != null) |
| _cl = new AntClassLoader(getProject(), classpath, useParent); |
| else |
| _cl = new AntClassLoader(getProject().getCoreLoader(), getProject(), |
| new Path(getProject()), useParent); |
| _cl.setIsolated(isolate); |
| |
| return _cl; |
| } |
| |
| /** |
| * Helper method to throw a standard exception if the task is not given |
| * any files to execute on. Implementations might call this method as |
| * the first step in {@link #executeOn} to validate that they are given |
| * files to work on. |
| */ |
| protected void assertFiles(String[] files) { |
| if (files.length == 0) |
| throw new BuildException(_loc.get("no-filesets").getMessage()); |
| } |
| |
| public void setClasspath(Path classPath) { |
| createClasspath().append(classPath); |
| } |
| |
| public Path createClasspath() { |
| if (classpath == null) |
| classpath = new Path(getProject()); |
| return classpath.createPath(); |
| } |
| |
| public Object createConfig() { |
| return getConfiguration(); |
| } |
| |
| public void addFileset(FileSet set) { |
| fileSets.add(set); |
| } |
| |
| @Override |
| public void execute() throws BuildException { |
| // if the user didn't supply a conf file, load the default |
| if (_conf == null) |
| _conf = newConfiguration(); |
| ConfigurationProvider cp = null; |
| String propertiesResource = _conf.getPropertiesResource(); |
| if ( propertiesResource == null) { |
| cp = ProductDerivations.loadDefaults(getConfigPropertiesResourceLoader()); |
| } else if (_conf.isDeferResourceLoading() && !StringUtil.isEmpty(propertiesResource)) { |
| Map<String, String> result = Configurations.parseConfigResource(propertiesResource); |
| String path = result.get(Configurations.CONFIG_RESOURCE_PATH); |
| String anchor = result.get(Configurations.CONFIG_RESOURCE_ANCHOR); |
| cp = ProductDerivations.load(path, anchor, getConfigPropertiesResourceLoader()); |
| } |
| |
| if (cp != null){ |
| cp.setInto(_conf); |
| } |
| |
| String[] files = getFiles(); |
| try { |
| executeOn(files); |
| } catch (Throwable e) { |
| e.printStackTrace(); |
| if (haltOnError) |
| throw new BuildException(e); |
| } finally { |
| _conf.close(); |
| _conf = null; |
| } |
| } |
| |
| private MultiClassLoader getConfigPropertiesResourceLoader() { |
| MultiClassLoader loader = AccessController |
| .doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction()); |
| loader.addClassLoader(getClassLoader()); |
| loader.addClassLoader(AccessController.doPrivileged( |
| J2DoPrivHelper.getClassLoaderAction(_conf.getClass()))); |
| return loader; |
| } |
| |
| private String[] getFiles() { |
| List<String> files = new ArrayList<>(); |
| for(FileSet fs : fileSets) { |
| DirectoryScanner ds = fs.getDirectoryScanner(getProject()); |
| |
| String[] dsFiles = ds.getIncludedFiles(); |
| for (int j = 0; j < dsFiles.length; j++) { |
| File f = new File(dsFiles[j]); |
| if (!AccessController.doPrivileged(J2DoPrivHelper |
| .isFileAction(f))) |
| f = new File(ds.getBasedir(), dsFiles[j]); |
| files.add(AccessController.doPrivileged( |
| J2DoPrivHelper.getAbsolutePathAction(f))); |
| } |
| } |
| return (String[]) files.toArray(new String[files.size()]); |
| } |
| } |
| |