001/*
002 * Copyright (C) 2009 Christian Schulte <cs@schulte.it>
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without
006 * modification, are permitted provided that the following conditions
007 * are met:
008 *
009 *   o Redistributions of source code must retain the above copyright
010 *     notice, this list of conditions and the following disclaimer.
011 *
012 *   o Redistributions in binary form must reproduce the above copyright
013 *     notice, this list of conditions and the following disclaimer in
014 *     the documentation and/or other materials provided with the
015 *     distribution.
016 *
017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027 *
028 * $JOMC: AbstractModelCommand.java 5253 2016-04-25 20:18:36Z schulte $
029 *
030 */
031package org.jomc.cli.commands;
032
033import java.io.File;
034import java.util.logging.Level;
035import javax.xml.bind.JAXBElement;
036import javax.xml.bind.JAXBException;
037import javax.xml.bind.Unmarshaller;
038import org.apache.commons.cli.CommandLine;
039import org.jomc.model.Module;
040import org.jomc.model.Modules;
041import org.jomc.model.modlet.DefaultModelProcessor;
042import org.jomc.model.modlet.DefaultModelProvider;
043import org.jomc.model.modlet.DefaultModelValidator;
044import org.jomc.model.modlet.ModelHelper;
045import org.jomc.modlet.Model;
046import org.jomc.modlet.ModelContext;
047import org.jomc.modlet.ModelException;
048import org.jomc.tools.modlet.ToolsModelProcessor;
049import org.jomc.tools.modlet.ToolsModelProvider;
050
051/**
052 * {@code Model} based command implementation.
053 *
054 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
055 */
056public abstract class AbstractModelCommand extends AbstractModletCommand
057{
058
059    /**
060     * Creates a new {@code AbstractModelCommand} instance.
061     */
062    public AbstractModelCommand()
063    {
064        super();
065    }
066
067    @Override
068    public org.apache.commons.cli.Options getOptions()
069    {
070        final org.apache.commons.cli.Options options = super.getOptions();
071        options.addOption( Options.MODULE_LOCATION_OPTION );
072        options.addOption( Options.TRANSFORMER_LOCATION_OPTION );
073        options.addOption( Options.NO_CLASSPATH_RESOLUTION_OPTION );
074        options.addOption( Options.NO_MODEL_PROCESSING_OPTION );
075        options.addOption( Options.NO_MODEL_RESOURCE_VALIDATION_OPTION );
076        options.addOption( Options.NO_JAVA_VALIDATION_OPTION );
077        return options;
078    }
079
080    /**
081     * {@inheritDoc}
082     */
083    @Override
084    protected ModelContext createModelContext( final CommandLine commandLine, final ClassLoader classLoader )
085        throws CommandExecutionException
086    {
087        if ( commandLine == null )
088        {
089            throw new NullPointerException( "commandLine" );
090        }
091
092        final ModelContext modelContext = super.createModelContext( commandLine, classLoader );
093
094        if ( commandLine.hasOption( Options.TRANSFORMER_LOCATION_OPTION.getOpt() ) )
095        {
096            modelContext.setAttribute( DefaultModelProcessor.TRANSFORMER_LOCATION_ATTRIBUTE_NAME,
097                                       commandLine.getOptionValue( Options.TRANSFORMER_LOCATION_OPTION.getOpt() ) );
098
099        }
100
101        if ( commandLine.hasOption( Options.MODULE_LOCATION_OPTION.getOpt() ) )
102        {
103            modelContext.setAttribute( DefaultModelProvider.MODULE_LOCATION_ATTRIBUTE_NAME,
104                                       commandLine.getOptionValue( Options.MODULE_LOCATION_OPTION.getOpt() ) );
105
106        }
107
108        modelContext.setAttribute( ToolsModelProvider.MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME,
109                                   !commandLine.hasOption( Options.NO_CLASSPATH_RESOLUTION_OPTION.getOpt() ) );
110
111        modelContext.setAttribute( ToolsModelProcessor.MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME,
112                                   !commandLine.hasOption( Options.NO_CLASSPATH_RESOLUTION_OPTION.getOpt() ) );
113
114        modelContext.setAttribute( DefaultModelProvider.VALIDATING_ATTRIBUTE_NAME,
115                                   !commandLine.hasOption( Options.NO_MODEL_RESOURCE_VALIDATION_OPTION.getOpt() ) );
116
117        modelContext.setAttribute( DefaultModelValidator.VALIDATE_JAVA_ATTRIBUTE_NAME,
118                                   !commandLine.hasOption( Options.NO_JAVA_VALIDATION_OPTION.getOpt() ) );
119
120        return modelContext;
121    }
122
123    /**
124     * Gets the model as specified by a given command line.
125     *
126     * @param context The context to use for getting the model.
127     * @param commandLine The command line specifying the model to get.
128     *
129     * @return The model as specified by {@code commandLine}.
130     *
131     * @throws CommandExecutionException if getting the model fails.
132     */
133    protected Model getModel( final ModelContext context, final CommandLine commandLine )
134        throws CommandExecutionException
135    {
136        try
137        {
138            Model model = new Model();
139            model.setIdentifier( this.getModel( commandLine ) );
140            Modules modules = new Modules();
141            ModelHelper.setModules( model, modules );
142
143            if ( commandLine.hasOption( Options.DOCUMENTS_OPTION.getOpt() ) )
144            {
145                final Unmarshaller u = context.createUnmarshaller( model.getIdentifier() );
146
147                if ( !commandLine.hasOption( Options.NO_MODEL_RESOURCE_VALIDATION_OPTION.getOpt() ) )
148                {
149                    u.setSchema( context.createSchema( model.getIdentifier() ) );
150                }
151
152                for ( final File f : this.getDocumentFiles( commandLine ) )
153                {
154                    if ( this.isLoggable( Level.FINEST ) )
155                    {
156                        this.log( Level.FINEST,
157                                  Messages.getMessage( "readingResource", f.getAbsolutePath() ),
158                                  null );
159
160                    }
161
162                    Object o = u.unmarshal( f );
163                    if ( o instanceof JAXBElement<?> )
164                    {
165                        o = ( (JAXBElement<?>) o ).getValue();
166                    }
167
168                    if ( o instanceof Module )
169                    {
170                        modules.getModule().add( (Module) o );
171                    }
172                    else if ( o instanceof Modules )
173                    {
174                        modules.getModule().addAll( ( (Modules) o ).getModule() );
175                    }
176                    else if ( this.isLoggable( Level.WARNING ) )
177                    {
178                        this.log( Level.WARNING,
179                                  Messages.getMessage( "failureProcessing", f.getAbsolutePath(), o.toString() ),
180                                  null );
181
182                    }
183                }
184            }
185
186            model = context.findModel( model );
187            modules = ModelHelper.getModules( model );
188
189            if ( modules != null && !commandLine.hasOption( Options.NO_CLASSPATH_RESOLUTION_OPTION.getOpt() ) )
190            {
191                final Module classpathModule = modules.getClasspathModule(
192                    Modules.getDefaultClasspathModuleName(), context.getClassLoader() );
193
194                if ( classpathModule != null && modules.getModule( classpathModule.getName() ) == null )
195                {
196                    modules.getModule().add( classpathModule );
197                }
198            }
199
200            if ( !commandLine.hasOption( Options.NO_MODEL_PROCESSING_OPTION.getOpt() ) )
201            {
202                model = context.processModel( model );
203                modules = ModelHelper.getModules( model );
204            }
205
206            assert modules != null : "Modules '" + this.getModel( commandLine ) + "' not found.";
207            return model;
208        }
209        catch ( final ModelException e )
210        {
211            throw new CommandExecutionException( Messages.getMessage( e ), e );
212        }
213        catch ( final JAXBException e )
214        {
215            String message = Messages.getMessage( e );
216            if ( message == null )
217            {
218                message = Messages.getMessage( e.getLinkedException() );
219            }
220
221            throw new CommandExecutionException( message, e );
222        }
223    }
224
225}