org.apache.maven.archetype.old.DefaultOldArchetype.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.maven.archetype.old.DefaultOldArchetype.java

Source

package org.apache.maven.archetype.old;

/*
 * 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.
 */

import org.apache.commons.io.input.XmlStreamReader;
import org.apache.maven.archetype.ArchetypeGenerationRequest;
import org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor;
import org.apache.maven.archetype.old.descriptor.ArchetypeDescriptorBuilder;
import org.apache.maven.archetype.old.descriptor.TemplateDescriptor;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.archetype.common.ArchetypeArtifactManager;
import org.apache.maven.archetype.common.Constants;
import org.apache.maven.archetype.exception.UnknownArchetype;
import org.apache.maven.model.Build;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.Resource;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.codehaus.plexus.velocity.VelocityComponent;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
 * @version $Id$
 */
@Component(role = OldArchetype.class)
public class DefaultOldArchetype extends AbstractLogEnabled implements OldArchetype {
    private static final String DEFAULT_TEST_RESOURCE_DIR = "/src/test/resources";

    private static final String DEFAULT_TEST_SOURCE_DIR = "/src/test/java";

    private static final String DEFAULT_RESOURCE_DIR = "/src/main/resources";

    private static final String DEFAULT_SOURCE_DIR = "/src/main/java";

    // ----------------------------------------------------------------------
    // Components
    // ----------------------------------------------------------------------

    @Requirement
    private VelocityComponent velocity;

    @Requirement
    private ArchetypeArtifactManager archetypeArtifactManager;

    // ----------------------------------------------------------------------
    // Implementation
    // ----------------------------------------------------------------------

    // groupId = maven
    // artifactId = maven-foo-archetype
    // version = latest

    public void createArchetype(ArchetypeGenerationRequest request, ArtifactRepository archetypeRepository)
            throws UnknownArchetype, ArchetypeNotFoundException, ArchetypeDescriptorException,
            ArchetypeTemplateProcessingException {
        // ----------------------------------------------------------------------
        // Download the archetype
        // ----------------------------------------------------------------------

        File archetypeFile = archetypeArtifactManager.getArchetypeFile(request.getArchetypeGroupId(),
                request.getArchetypeArtifactId(), request.getArchetypeVersion(), archetypeRepository,
                request.getLocalRepository(), request.getRemoteArtifactRepositories());

        createArchetype(request, archetypeFile);
    }

    public void createArchetype(ArchetypeGenerationRequest request, File archetypeFile)
            throws ArchetypeDescriptorException, ArchetypeTemplateProcessingException {
        Map<String, String> parameters = new HashMap<String, String>();

        parameters.put("basedir", request.getOutputDirectory());

        parameters.put(Constants.PACKAGE, request.getPackage());

        parameters.put("packageName", request.getPackage());

        parameters.put(Constants.GROUP_ID, request.getGroupId());

        parameters.put(Constants.ARTIFACT_ID, request.getArtifactId());

        parameters.put(Constants.VERSION, request.getVersion());

        // ---------------------------------------------------------------------
        // Get Logger and display all parameters used
        // ---------------------------------------------------------------------
        if (getLogger().isInfoEnabled()) {
            getLogger().info("----------------------------------------------------------------------------");

            getLogger().info("Using following parameters for creating project from Old (1.x) Archetype: "
                    + request.getArchetypeArtifactId() + ":" + request.getArchetypeVersion());

            getLogger().info("----------------------------------------------------------------------------");

            for (Map.Entry<String, String> entry : parameters.entrySet()) {
                String parameterName = entry.getKey();

                String parameterValue = entry.getValue();

                getLogger().info("Parameter: " + parameterName + ", Value: " + parameterValue);
            }
        }

        // ----------------------------------------------------------------------
        // Load the descriptor
        // ----------------------------------------------------------------------

        ArchetypeDescriptorBuilder builder = new ArchetypeDescriptorBuilder();

        ArchetypeDescriptor descriptor;

        URLClassLoader archetypeJarLoader;

        InputStream is = null;

        try {
            URL[] urls = new URL[1];

            urls[0] = archetypeFile.toURL();

            archetypeJarLoader = new URLClassLoader(urls);

            is = getStream(ARCHETYPE_DESCRIPTOR, archetypeJarLoader);

            if (is == null) {
                is = getStream(ARCHETYPE_OLD_DESCRIPTOR, archetypeJarLoader);
            }

            if (is == null) {
                throw new ArchetypeDescriptorException(
                        "The " + ARCHETYPE_DESCRIPTOR + " descriptor cannot be found.");
            }

            descriptor = builder.build(new XmlStreamReader(is));
        } catch (IOException e) {
            throw new ArchetypeDescriptorException("Error reading the " + ARCHETYPE_DESCRIPTOR + " descriptor.", e);
        } catch (XmlPullParserException e) {
            throw new ArchetypeDescriptorException("Error reading the " + ARCHETYPE_DESCRIPTOR + " descriptor.", e);
        } finally {
            IOUtil.close(is);
        }

        // ----------------------------------------------------------------------
        //
        // ----------------------------------------------------------------------

        String artifactId = request.getArtifactId();

        File parentPomFile = new File(request.getOutputDirectory(), ARCHETYPE_POM);

        File outputDirectoryFile;

        boolean creating;
        File pomFile;
        if (parentPomFile.exists() && descriptor.isAllowPartial() && artifactId == null) {
            outputDirectoryFile = new File(request.getOutputDirectory());
            creating = false;
            pomFile = parentPomFile;
        } else {
            if (artifactId == null) {
                throw new ArchetypeTemplateProcessingException(
                        "Artifact ID must be specified when creating a new project from an archetype.");
            }

            outputDirectoryFile = new File(request.getOutputDirectory(), artifactId);
            creating = true;

            if (outputDirectoryFile.exists()) {
                if (descriptor.isAllowPartial()) {
                    creating = false;
                } else {
                    throw new ArchetypeTemplateProcessingException("Directory " + outputDirectoryFile.getName()
                            + " already exists - please run from a clean directory");
                }
            }

            pomFile = new File(outputDirectoryFile, ARCHETYPE_POM);
        }

        if (creating) {
            if (request.getGroupId() == null) {
                throw new ArchetypeTemplateProcessingException(
                        "Group ID must be specified when creating a new project from an archetype.");
            }

            if (request.getVersion() == null) {
                throw new ArchetypeTemplateProcessingException(
                        "Version must be specified when creating a new project from an archetype.");
            }
        }

        String outputDirectory = outputDirectoryFile.getAbsolutePath();

        String packageName = request.getPackage();

        // ----------------------------------------------------------------------
        // Set up the Velocity context
        // ----------------------------------------------------------------------

        Context context = new VelocityContext();

        context.put(Constants.PACKAGE, packageName);

        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            context.put(entry.getKey(), entry.getValue());
        }

        // ----------------------------------------------------------------------
        // Process the templates
        // ----------------------------------------------------------------------

        ClassLoader old = Thread.currentThread().getContextClassLoader();

        Thread.currentThread().setContextClassLoader(archetypeJarLoader);

        Model parentModel = null;
        if (creating) {
            if (parentPomFile.exists()) {
                Reader fileReader = null;

                try {
                    fileReader = ReaderFactory.newXmlReader(parentPomFile);
                    MavenXpp3Reader reader = new MavenXpp3Reader();
                    parentModel = reader.read(fileReader);
                    if (!"pom".equals(parentModel.getPackaging())) {
                        throw new ArchetypeTemplateProcessingException(
                                "Unable to add module to the current project as it is not of packaging type 'pom'");
                    }
                } catch (IOException e) {
                    throw new ArchetypeTemplateProcessingException("Unable to read parent POM", e);
                } catch (XmlPullParserException e) {
                    throw new ArchetypeTemplateProcessingException("Unable to read parent POM", e);
                } finally {
                    IOUtil.close(fileReader);
                }

                parentModel.getModules().add(artifactId);
            }
        }

        try {
            processTemplates(pomFile, outputDirectory, context, descriptor, packageName, parentModel);
        } finally {
            Thread.currentThread().setContextClassLoader(old);
        }

        if (parentModel != null) {
            /*
                    // TODO: would be nice to just write out with the xpp3 writer again, except that it loses a bunch of info and
                    // reformats, so the module is just baked in as a string instead.
                        FileWriter fileWriter = null;
                
                        try
                        {
            fileWriter = new FileWriter( parentPomFile );
                
            MavenXpp3Writer writer = new MavenXpp3Writer();
            writer.write( fileWriter, parentModel );
                        }
                        catch ( IOException e )
                        {
            throw new ArchetypeTemplateProcessingException( "Unable to rewrite parent POM", e );
                        }
                        finally
                        {
            IOUtil.close( fileWriter );
                        }
            */
            Reader fileReader = null;
            boolean added;
            StringWriter w = new StringWriter();
            try {
                fileReader = ReaderFactory.newXmlReader(parentPomFile);
                added = addModuleToParentPom(artifactId, fileReader, w);
            } catch (IOException e) {
                throw new ArchetypeTemplateProcessingException("Unable to rewrite parent POM", e);
            } catch (DocumentException e) {
                throw new ArchetypeTemplateProcessingException("Unable to rewrite parent POM", e);
            } finally {
                IOUtil.close(fileReader);
            }

            if (added) {
                Writer out = null;
                try {
                    out = WriterFactory.newXmlWriter(parentPomFile);
                    IOUtil.copy(w.toString(), out);
                } catch (IOException e) {
                    throw new ArchetypeTemplateProcessingException("Unable to rewrite parent POM", e);
                } finally {
                    IOUtil.close(out);
                }
            }
        }

        // ----------------------------------------------------------------------
        // Log message on OldArchetype creation
        // ----------------------------------------------------------------------
        if (getLogger().isInfoEnabled()) {
            getLogger().info("project created from Old (1.x) Archetype in dir: " + outputDirectory);
        }

    }

    static boolean addModuleToParentPom(String artifactId, Reader fileReader, Writer fileWriter)
            throws DocumentException, IOException, ArchetypeTemplateProcessingException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(fileReader);
        Element project = document.getRootElement();

        String packaging = null;
        Element packagingElement = project.element("packaging");
        if (packagingElement != null) {
            packaging = packagingElement.getStringValue();
        }
        if (!"pom".equals(packaging)) {
            throw new ArchetypeTemplateProcessingException(
                    "Unable to add module to the current project as it is not of packaging type 'pom'");
        }

        Element modules = project.element("modules");
        if (modules == null) {
            modules = project.addText("  ").addElement("modules");
            modules.setText("\n  ");
            project.addText("\n");
        }
        boolean found = false;
        for (Iterator<?> i = modules.elementIterator("module"); i.hasNext() && !found;) {
            Element module = (Element) i.next();
            if (module.getText().equals(artifactId)) {
                found = true;
            }
        }
        if (!found) {
            Node lastTextNode = null;
            for (Iterator<?> i = modules.nodeIterator(); i.hasNext();) {
                Node node = (Node) i.next();
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    lastTextNode = null;
                } else if (node.getNodeType() == Node.TEXT_NODE) {
                    lastTextNode = node;
                }
            }

            if (lastTextNode != null) {
                modules.remove(lastTextNode);
            }

            modules.addText("\n    ");
            modules.addElement("module").setText(artifactId);
            modules.addText("\n  ");

            XMLWriter writer = new XMLWriter(fileWriter);
            writer.write(document);
        }
        return !found;
    }

    private void processTemplates(File pomFile, String outputDirectory, Context context,
            ArchetypeDescriptor descriptor, String packageName, Model parentModel)
            throws ArchetypeTemplateProcessingException {
        if (!pomFile.exists()) {
            processTemplate(outputDirectory, context, ARCHETYPE_POM, new TemplateDescriptor(), false, null);
        }

        // ---------------------------------------------------------------------
        // Model generated for the new archetype, so process it now
        // ---------------------------------------------------------------------

        Model generatedModel;
        Reader pomReader = null;
        try {
            pomReader = ReaderFactory.newXmlReader(pomFile);

            MavenXpp3Reader reader = new MavenXpp3Reader();

            generatedModel = reader.read(pomReader);
        } catch (IOException e) {
            throw new ArchetypeTemplateProcessingException("Error reading POM", e);
        } catch (XmlPullParserException e) {
            throw new ArchetypeTemplateProcessingException("Error reading POM", e);
        } finally {
            IOUtil.close(pomReader);
        }

        if (parentModel != null) {
            Parent parent = new Parent();
            parent.setGroupId(parentModel.getGroupId());
            if (parent.getGroupId() == null) {
                parent.setGroupId(parentModel.getParent().getGroupId());
            }
            parent.setArtifactId(parentModel.getArtifactId());
            parent.setVersion(parentModel.getVersion());
            if (parent.getVersion() == null) {
                parent.setVersion(parentModel.getParent().getVersion());
            }
            generatedModel.setParent(parent);

            Writer pomWriter = null;
            try {
                pomWriter = WriterFactory.newXmlWriter(pomFile);

                MavenXpp3Writer writer = new MavenXpp3Writer();
                writer.write(pomWriter, generatedModel);
            } catch (IOException e) {
                throw new ArchetypeTemplateProcessingException("Error rewriting POM", e);
            } finally {
                IOUtil.close(pomWriter);
            }
        }

        // XXX: Following POM processing block may be a candidate for
        // refactoring out into service methods or moving to
        // createProjectDirectoryStructure(outputDirectory)
        Build build = generatedModel.getBuild();

        boolean overrideSrcDir = false;

        boolean overrideResourceDir = false;

        boolean overrideTestSrcDir = false;

        boolean overrideTestResourceDir = false;

        boolean foundBuildElement = build != null;

        if (getLogger().isDebugEnabled()) {
            getLogger().debug(
                    "********************* Debug info for resources created from generated Model ***********************");
            getLogger().debug("Was build element found in generated POM?: " + foundBuildElement);
        }

        // create source directory if specified in POM
        if (foundBuildElement && null != build.getSourceDirectory()) {
            getLogger().debug("Overriding default source directory ");

            overrideSrcDir = true;

            String srcDirectory = build.getSourceDirectory();

            srcDirectory = StringUtils.replace(srcDirectory, "\\", "/");

            FileUtils.mkdir(getOutputDirectory(outputDirectory, srcDirectory));
        }

        // create script source directory if specified in POM
        if (foundBuildElement && null != build.getScriptSourceDirectory()) {
            getLogger().debug("Overriding default script source directory ");

            String scriptSourceDirectory = build.getScriptSourceDirectory();

            scriptSourceDirectory = StringUtils.replace(scriptSourceDirectory, "\\", "/");

            FileUtils.mkdir(getOutputDirectory(outputDirectory, scriptSourceDirectory));
        }

        // create resource director(y/ies) if specified in POM
        if (foundBuildElement && build.getResources().size() > 0) {
            getLogger().debug("Overriding default resource directory ");

            overrideResourceDir = true;

            Iterator<?> resourceItr = build.getResources().iterator();

            while (resourceItr.hasNext()) {
                Resource resource = (Resource) resourceItr.next();

                String resourceDirectory = resource.getDirectory();

                resourceDirectory = StringUtils.replace(resourceDirectory, "\\", "/");

                FileUtils.mkdir(getOutputDirectory(outputDirectory, resourceDirectory));
            }
        }
        // create test source directory if specified in POM
        if (foundBuildElement && null != build.getTestSourceDirectory()) {
            getLogger().debug("Overriding default test directory ");

            overrideTestSrcDir = true;

            String testDirectory = build.getTestSourceDirectory();

            testDirectory = StringUtils.replace(testDirectory, "\\", "/");

            FileUtils.mkdir(getOutputDirectory(outputDirectory, testDirectory));
        }

        // create test resource directory if specified in POM
        if (foundBuildElement && build.getTestResources().size() > 0) {
            getLogger().debug("Overriding default test resource directory ");

            overrideTestResourceDir = true;

            Iterator<?> testResourceItr = build.getTestResources().iterator();

            while (testResourceItr.hasNext()) {
                Resource resource = (Resource) testResourceItr.next();

                String testResourceDirectory = resource.getDirectory();

                testResourceDirectory = StringUtils.replace(testResourceDirectory, "\\", "/");

                FileUtils.mkdir(getOutputDirectory(outputDirectory, testResourceDirectory));
            }
        }

        getLogger().debug(
                "********************* End of debug info from resources from generated POM ***********************");

        // ----------------------------------------------------------------------
        // Main
        // ----------------------------------------------------------------------

        if (descriptor.getSources().size() > 0) {
            if (!overrideSrcDir) {
                FileUtils.mkdir(outputDirectory + DEFAULT_SOURCE_DIR);
                processSources(outputDirectory, context, descriptor, packageName, DEFAULT_SOURCE_DIR);
            } else {
                processSources(outputDirectory, context, descriptor, packageName, build.getSourceDirectory());
            }
        }

        if (descriptor.getResources().size() > 0) {
            if (!overrideResourceDir) {
                FileUtils.mkdir(outputDirectory + DEFAULT_RESOURCE_DIR);
            }
            processResources(outputDirectory, context, descriptor, packageName);
        }

        // ----------------------------------------------------------------------
        // Test
        // ----------------------------------------------------------------------

        if (descriptor.getTestSources().size() > 0) {
            if (!overrideTestSrcDir) {
                FileUtils.mkdir(outputDirectory + DEFAULT_TEST_SOURCE_DIR);
                processTestSources(outputDirectory, context, descriptor, packageName, DEFAULT_TEST_SOURCE_DIR);
            } else {
                processTestSources(outputDirectory, context, descriptor, packageName,
                        build.getTestSourceDirectory());
            }
        }

        if (descriptor.getTestResources().size() > 0) {
            if (!overrideTestResourceDir) {
                FileUtils.mkdir(outputDirectory + DEFAULT_TEST_RESOURCE_DIR);
            }
            processTestResources(outputDirectory, context, descriptor, packageName);
        }

        // ----------------------------------------------------------------------
        // Site
        // ----------------------------------------------------------------------

        if (descriptor.getSiteResources().size() > 0) {
            processSiteResources(outputDirectory, context, descriptor, packageName);
        }
    }

    private void processTemplate(String outputDirectory, Context context, String template,
            TemplateDescriptor descriptor, boolean packageInFileName, String packageName)
            throws ArchetypeTemplateProcessingException {
        processTemplate(outputDirectory, context, template, descriptor, packageInFileName, packageName, null);
    }

    private String getOutputDirectory(String outputDirectory, String testResourceDirectory) {
        return outputDirectory
                + (testResourceDirectory.startsWith("/") ? testResourceDirectory : "/" + testResourceDirectory);
    }

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    protected void processSources(String outputDirectory, Context context, ArchetypeDescriptor descriptor,
            String packageName, String sourceDirectory) throws ArchetypeTemplateProcessingException {
        for (String template : descriptor.getSources()) {
            processTemplate(outputDirectory, context, template, descriptor.getSourceDescriptor(template), true,
                    packageName, sourceDirectory);
        }
    }

    protected void processTestSources(String outputDirectory, Context context, ArchetypeDescriptor descriptor,
            String packageName, String testSourceDirectory) throws ArchetypeTemplateProcessingException {
        for (String template : descriptor.getTestSources()) {
            processTemplate(outputDirectory, context, template, descriptor.getTestSourceDescriptor(template), true,
                    packageName, testSourceDirectory);
        }
    }

    protected void processResources(String outputDirectory, Context context, ArchetypeDescriptor descriptor,
            String packageName) throws ArchetypeTemplateProcessingException {
        for (String template : descriptor.getResources()) {
            processTemplate(outputDirectory, context, template, descriptor.getResourceDescriptor(template), false,
                    packageName);
        }
    }

    protected void processTestResources(String outputDirectory, Context context, ArchetypeDescriptor descriptor,
            String packageName) throws ArchetypeTemplateProcessingException {
        for (String template : descriptor.getTestResources()) {
            processTemplate(outputDirectory, context, template, descriptor.getTestResourceDescriptor(template),
                    false, packageName);
        }
    }

    protected void processSiteResources(String outputDirectory, Context context, ArchetypeDescriptor descriptor,
            String packageName) throws ArchetypeTemplateProcessingException {
        for (String template : descriptor.getSiteResources()) {
            processTemplate(outputDirectory, context, template, descriptor.getSiteResourceDescriptor(template),
                    false, packageName);
        }
    }

    protected void processTemplate(String outputDirectory, Context context, String template,
            TemplateDescriptor descriptor, boolean packageInFileName, String packageName, String sourceDirectory)
            throws ArchetypeTemplateProcessingException {
        File f;

        template = StringUtils.replace(template, "\\", "/");

        if (packageInFileName && packageName != null) {
            String templateFileName = StringUtils.replace(template, "/", File.separator);

            String path = packageName.replace('.', '/');

            String filename = FileUtils.filename(templateFileName);

            String dirname = FileUtils.dirname(templateFileName).replace('\\', '/');

            sourceDirectory = sourceDirectory.replace('\\', '/');
            if (sourceDirectory.startsWith("/")) {
                sourceDirectory = sourceDirectory.substring(1);
            }

            if (!dirname.startsWith(sourceDirectory)) {
                throw new ArchetypeTemplateProcessingException(
                        "Template '" + template + "' not in directory '" + sourceDirectory + "'");
            }

            String extraPackages = dirname.substring(sourceDirectory.length());
            if (extraPackages.startsWith("/")) {
                extraPackages = extraPackages.substring(1);
            }
            if (extraPackages.length() > 0) {
                path += "/" + extraPackages;
            }

            f = new File(new File(new File(outputDirectory, sourceDirectory), path), filename);
        } else {
            f = new File(outputDirectory, template);
        }

        if (!f.getParentFile().exists()) {
            f.getParentFile().mkdirs();
        }

        if (descriptor.isFiltered()) {
            Writer writer = null;
            try {
                StringWriter stringWriter = new StringWriter();

                template = ARCHETYPE_RESOURCES + "/" + template;

                velocity.getEngine().mergeTemplate(template, descriptor.getEncoding(), context, stringWriter);

                writer = new OutputStreamWriter(new FileOutputStream(f), descriptor.getEncoding());

                writer.write(StringUtils.unifyLineSeparators(stringWriter.toString()));

                writer.flush();
            } catch (Exception e) {
                throw new ArchetypeTemplateProcessingException("Error merging velocity templates", e);
            } finally {
                IOUtil.close(writer);
            }
        } else {
            InputStream is = getStream(ARCHETYPE_RESOURCES + "/" + template, null);

            OutputStream fos = null;

            try {
                fos = new FileOutputStream(f);

                IOUtil.copy(is, fos);
            } catch (Exception e) {
                throw new ArchetypeTemplateProcessingException("Error copying file", e);
            } finally {
                IOUtil.close(fos);

                IOUtil.close(is);
            }
        }
    }

    protected void createProjectDirectoryStructure(String outputDirectory) {
    }

    private InputStream getStream(String name, ClassLoader loader) {
        if (loader == null) {
            return Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
        }
        return loader.getResourceAsStream(name);
    }
}