001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import org.apache.tools.ant.BuildException;
022: import org.apache.tools.ant.ProjectHelper;
023: import org.apache.tools.ant.Project;
024: import org.apache.tools.ant.Task;
025: import org.apache.tools.ant.util.FileUtils;
026:
027: import java.io.File;
028: import java.util.Vector;
029:
030: /**
031: * Task to import another build file into the current project.
032: * <p>
033: * It must be 'top level'. On execution it will read another Ant file
034: * into the same Project.
035: * </p>
036: * <p>
037: * <b>Important</b>: we have not finalized how relative file references
038: * will be resolved in deep/complex build hierarchies - such as what happens
039: * when an imported file imports another file. Use absolute references for
040: * enhanced build file stability, especially in the imported files.
041: * </p>
042: * <p>Examples:</p>
043: * <pre>
044: * <import file="../common-targets.xml"/>
045: * </pre>
046: * <p>Import targets from a file in a parent directory.</p>
047: * <pre>
048: * <import file="${deploy-platform}.xml"/>
049: * </pre>
050: * <p>Import the project defined by the property <code>deploy-platform</code>.</p>
051: *
052: * @since Ant1.6
053: * @ant.task category="control"
054: */
055: public class ImportTask extends Task {
056: private String file;
057: private boolean optional;
058: private static final FileUtils FILE_UTILS = FileUtils
059: .getFileUtils();
060:
061: /**
062: * sets the optional attribute
063: *
064: * @param optional if true ignore files that are not present,
065: * default is false
066: */
067: public void setOptional(boolean optional) {
068: this .optional = optional;
069: }
070:
071: /**
072: * the name of the file to import. How relative paths are resolved is still
073: * in flux: use absolute paths for safety.
074: * @param file the name of the file
075: */
076: public void setFile(String file) {
077: // I don't think we can use File - different rules
078: // for relative paths.
079: this .file = file;
080: }
081:
082: /**
083: * This relies on the task order model.
084: *
085: */
086: public void execute() {
087: if (file == null) {
088: throw new BuildException("import requires file attribute");
089: }
090: if (getOwningTarget() == null
091: || !"".equals(getOwningTarget().getName())) {
092: throw new BuildException(
093: "import only allowed as a top-level task");
094: }
095:
096: ProjectHelper helper = (ProjectHelper) getProject()
097: .getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
098:
099: if (helper == null) {
100: // this happens if the projecthelper was not registered with the project.
101: throw new BuildException(
102: "import requires support in ProjectHelper");
103: }
104:
105: Vector importStack = helper.getImportStack();
106:
107: if (importStack.size() == 0) {
108: // this happens if ant is used with a project
109: // helper that doesn't set the import.
110: throw new BuildException(
111: "import requires support in ProjectHelper");
112: }
113:
114: if (getLocation() == null
115: || getLocation().getFileName() == null) {
116: throw new BuildException(
117: "Unable to get location of import task");
118: }
119:
120: File buildFile = new File(getLocation().getFileName())
121: .getAbsoluteFile();
122:
123: // Paths are relative to the build file they're imported from,
124: // *not* the current directory (same as entity includes).
125:
126: File buildFileParent = new File(buildFile.getParent());
127: File importedFile = FILE_UTILS.resolveFile(buildFileParent,
128: file);
129:
130: getProject().log(
131: "Importing file " + importedFile + " from "
132: + buildFile.getAbsolutePath(),
133: Project.MSG_VERBOSE);
134:
135: if (!importedFile.exists()) {
136: String message = "Cannot find " + file + " imported from "
137: + buildFile.getAbsolutePath();
138: if (optional) {
139: getProject().log(message, Project.MSG_VERBOSE);
140: return;
141: } else {
142: throw new BuildException(message);
143: }
144: }
145:
146: if (importStack.contains(importedFile)) {
147: getProject().log(
148: "Skipped already imported file:\n "
149: + importedFile + "\n", Project.MSG_VERBOSE);
150: return;
151: }
152:
153: try {
154: helper.parse(getProject(), importedFile);
155: } catch (BuildException ex) {
156: throw ProjectHelper.addLocationToBuildException(ex,
157: getLocation());
158: }
159: }
160:
161: }
|