org.artificer.devsvr.ArtificerDevServer.java Source code

Java tutorial

Introduction

Here is the source code for org.artificer.devsvr.ArtificerDevServer.java

Source

/*
 * Copyright 2013 JBoss Inc
 *
 * Licensed 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.artificer.devsvr;

import org.apache.commons.io.IOUtils;
import org.artificer.client.ArtificerAtomApiClient;
import org.artificer.client.ArtificerClientException;
import org.artificer.common.ArtifactType;
import org.artificer.common.ArtificerModelUtils;
import org.artificer.common.error.ArtificerServerException;
import org.artificer.repository.filter.ServletCredentialsFilter;
import org.artificer.server.ArtificerLifeCycle;
import org.artificer.server.atom.services.ArtificerApplication;
import org.artificer.server.filters.MavenRepositoryAuthFilter;
import org.artificer.server.mvn.services.MavenFacadeServlet;
import org.artificer.ui.client.shared.beans.ArtifactSummaryBean;
import org.artificer.ui.server.api.KeycloakBearerTokenAuthenticationProvider;
import org.artificer.ui.server.filters.LocaleFilter;
import org.artificer.ui.server.servlets.ArtifactCreateServlet;
import org.artificer.ui.server.servlets.ArtifactDownloadServlet;
import org.artificer.ui.server.servlets.ArtifactUploadServlet;
import org.artificer.ui.server.servlets.KeyCloakLogoutServlet;
import org.artificer.ui.server.servlets.OntologyDownloadServlet;
import org.artificer.ui.server.servlets.OntologyUploadServlet;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType;
import org.overlord.commons.dev.server.DevServerEnvironment;
import org.overlord.commons.dev.server.ErraiDevServer;
import org.overlord.commons.dev.server.MultiDefaultServlet;
import org.overlord.commons.dev.server.discovery.ErraiWebAppModuleFromMavenDiscoveryStrategy;
import org.overlord.commons.dev.server.discovery.WebAppModuleFromIDEDiscoveryStrategy;
import org.overlord.commons.gwt.server.filters.GWTCacheControlFilter;
import org.overlord.commons.gwt.server.filters.ResourceCacheControlFilter;

import javax.security.auth.Subject;
import javax.servlet.DispatcherType;
import java.io.InputStream;
import java.security.Principal;
import java.util.EnumSet;

/**
 * A dev server for s-ramp.
 * @author eric.wittmann@redhat.com
 */
public class ArtificerDevServer extends ErraiDevServer {

    /**
     * Main entry point.
     * @param args
     */
    public static void main(String[] args) throws Exception {
        ArtificerDevServer devServer = new ArtificerDevServer(args);
        devServer.enableDebug();
        devServer.go();
    }

    /**
     * Constructor.
     * @param args
     */
    public ArtificerDevServer(String[] args) {
        super(args);
    }

    /**
     * @see org.overlord.commons.dev.server.ErraiDevServer#getErraiModuleId()
     */
    @Override
    protected String getErraiModuleId() {
        return "artificer-ui";
    }

    /**
     * @see org.overlord.commons.dev.server.DevServer#preConfig()
     */
    @Override
    protected void preConfig() {
        System.setProperty("artificer.file.storage", "filesystem");
        System.setProperty("artificer.file.storage.filesystem.path", "target/artificer-data");

        System.setProperty("hibernate.show_sql", "true");
        System.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
        System.setProperty("hibernate.connection.url", "jdbc:h2:mem:dbHibernateTest;DB_CLOSE_DELAY=-1;MVCC=true");
        System.setProperty("hibernate.connection.username", "sa");
        System.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        System.setProperty("hibernate.cache.use_second_level_cache", "false");
        System.setProperty("hibernate.cache.use_query_cache", "false");
        System.setProperty("hibernate.search.default.directory_provider", "ram");

        // Authentication provider
        System.setProperty("artificer-ui.atom-api.authentication.provider",
                KeycloakBearerTokenAuthenticationProvider.class.getName());

        // Don't do any resource caching!
        System.setProperty("overlord.resource-caching.disabled", "true");

        System.setProperty("artificer.config.events.jms.topics", "artificer/events/topic");
    }

    /**
     * @see org.overlord.commons.dev.server.DevServer#createDevEnvironment()
     */
    @Override
    protected DevServerEnvironment createDevEnvironment() {
        return new ArtificerDevServerEnvironment(args);
    }

    /**
     * @see org.overlord.commons.dev.server.DevServer#addModules(org.overlord.commons.dev.server.DevServerEnvironment)
     */
    @Override
    protected void addModules(DevServerEnvironment environment) {
        environment.addModule("artificer-ui", new WebAppModuleFromIDEDiscoveryStrategy(ArtifactSummaryBean.class),
                new ErraiWebAppModuleFromMavenDiscoveryStrategy(ArtifactSummaryBean.class));
    }

    /**
     * @see org.overlord.commons.dev.server.DevServer#addModulesToJetty(org.overlord.commons.dev.server.DevServerEnvironment, org.eclipse.jetty.server.handler.ContextHandlerCollection)
     */
    @Override
    protected void addModulesToJetty(DevServerEnvironment environment, ContextHandlerCollection handlers)
            throws Exception {
        super.addModulesToJetty(environment, handlers);

        /* *********
         * S-RAMP UI
         * ********* */
        ServletContextHandler artificerUI = new ServletContextHandler(ServletContextHandler.SESSIONS);
        artificerUI.setSecurityHandler(createSecurityHandler(true));
        artificerUI.setContextPath("/artificer-ui");
        artificerUI.setResourceBase(environment.getModuleDir("artificer-ui").getCanonicalPath());
        artificerUI.addFilter(GWTCacheControlFilter.class, "/app/*", EnumSet.of(DispatcherType.REQUEST));
        artificerUI.addFilter(GWTCacheControlFilter.class, "/rest/*", EnumSet.of(DispatcherType.REQUEST));
        artificerUI.addFilter(GWTCacheControlFilter.class, "/", EnumSet.of(DispatcherType.REQUEST));
        artificerUI.addFilter(GWTCacheControlFilter.class, "*.html", EnumSet.of(DispatcherType.REQUEST));
        artificerUI.addFilter(ResourceCacheControlFilter.class, "/css/*", EnumSet.of(DispatcherType.REQUEST));
        artificerUI.addFilter(ResourceCacheControlFilter.class, "/images/*", EnumSet.of(DispatcherType.REQUEST));
        artificerUI.addFilter(ResourceCacheControlFilter.class, "/js/*", EnumSet.of(DispatcherType.REQUEST));
        artificerUI.addFilter(LocaleFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));

        // Servlets
        artificerUI.addServlet(new ServletHolder(ArtifactUploadServlet.class), "/app/services/artifactUpload");
        artificerUI.addServlet(new ServletHolder(ArtifactCreateServlet.class), "/app/services/artifactCreate");
        artificerUI.addServlet(new ServletHolder(ArtifactDownloadServlet.class), "/app/services/artifactDownload");
        artificerUI.addServlet(new ServletHolder(OntologyUploadServlet.class), "/app/services/ontologyUpload");
        artificerUI.addServlet(new ServletHolder(OntologyDownloadServlet.class), "/app/services/ontologyDownload");
        artificerUI.addServlet(new ServletHolder(KeyCloakLogoutServlet.class), "/app/services/logout");
        ServletHolder resteasyUIServlet = new ServletHolder(new HttpServletDispatcher());
        resteasyUIServlet.setInitParameter("javax.ws.rs.Application", JettyArtificerApplication.class.getName());
        resteasyUIServlet.setInitParameter("resteasy.servlet.mapping.prefix", "/rest");
        artificerUI.addServlet(resteasyUIServlet, "/rest/*");
        // File resources
        ServletHolder resources = new ServletHolder(new MultiDefaultServlet());
        resources.setInitParameter("resourceBase", "/");
        resources.setInitParameter("resourceBases", environment.getModuleDir("artificer-ui").getCanonicalPath());
        resources.setInitParameter("dirAllowed", "true");
        resources.setInitParameter("pathInfoOnly", "false");
        String[] fileTypes = new String[] { "html", "js", "css", "png", "gif" };
        for (String fileType : fileTypes) {
            artificerUI.addServlet(resources, "*." + fileType);
        }

        // Jetty will 404 http://localhost:8080/artificer-ui, since a welcome file doesn't physically exist.  Instead,
        // setup a servlet on that root context and have it forward to /artificer-ui/index.html.
        artificerUI.addServlet(new ServletHolder(RootContextServlet.class), "/");

        /* *************
         * S-RAMP server
         * ************* */
        ServletContextHandler artificerServer = new ServletContextHandler(ServletContextHandler.SESSIONS);
        artificerServer.setSecurityHandler(createSecurityHandler(false));
        artificerServer.setContextPath("/artificer-server");
        artificerServer.addEventListener(new ArtificerLifeCycle());
        ServletHolder resteasyServerServlet = new ServletHolder(new HttpServletDispatcher());
        resteasyServerServlet.setInitParameter("javax.ws.rs.Application", ArtificerApplication.class.getName());
        artificerServer.addServlet(resteasyServerServlet, "/s-ramp/*");
        artificerServer.addServlet(resteasyServerServlet, "/artificer/*");
        //maven repository servlet:
        ServletHolder mvnServlet = new ServletHolder(new MavenFacadeServlet());
        artificerServer.addServlet(mvnServlet, "/maven/repository/*");
        artificerServer.addServlet(mvnServlet, "/maven/repository");
        // TODO enable JSP support to test the repository listing

        artificerServer.addFilter(BasicAuthFilter.class, "/s-ramp/*", EnumSet.of(DispatcherType.REQUEST))
                .setInitParameter("allowedIssuers", "/artificer-ui,/dtgov,/dtgov-ui");
        artificerServer.addFilter(BasicAuthFilter.class, "/artificer/*", EnumSet.of(DispatcherType.REQUEST))
                .setInitParameter("allowedIssuers", "/artificer-ui,/dtgov,/dtgov-ui");
        artificerServer
                .addFilter(MavenRepositoryAuthFilter.class, "/maven/repository/*",
                        EnumSet.of(DispatcherType.REQUEST))
                .setInitParameter("allowedIssuers", "/artificer-ui,/dtgov,/dtgov-ui");
        artificerServer.addFilter(org.artificer.server.filters.LocaleFilter.class, "/*",
                EnumSet.of(DispatcherType.REQUEST));
        artificerServer.addFilter(ServletCredentialsFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));

        // Add to handlers
        handlers.addHandler(artificerUI);
        handlers.addHandler(artificerServer);
    }

    /**
     * @return a security handler
     */
    private SecurityHandler createSecurityHandler(boolean forUI) {
        Constraint constraint = new Constraint();
        constraint.setName(Constraint.__BASIC_AUTH);
        constraint.setRoles(new String[] { "user" });
        constraint.setAuthenticate(true);

        ConstraintMapping cm = new ConstraintMapping();
        cm.setConstraint(constraint);
        cm.setPathSpec("/*");

        ConstraintSecurityHandler csh = new ConstraintSecurityHandler();
        csh.setSessionRenewedOnAuthentication(false);
        csh.setAuthenticator(new BasicAuthenticator());
        csh.setRealmName("artificer");
        if (forUI) {
            csh.addConstraintMapping(cm);
        }
        csh.setLoginService(new HashLoginService() {
            @Override
            public UserIdentity login(String username, Object credentials) {
                Credential credential = (credentials instanceof Credential) ? (Credential) credentials
                        : Credential.getCredential(credentials.toString());
                Principal userPrincipal = new KnownUser(username, credential);
                Subject subject = new Subject();
                subject.getPrincipals().add(userPrincipal);
                subject.getPrivateCredentials().add(credential);
                String[] roles = new String[] { "user", "readonly", "readwrite", "admin" };
                for (String role : roles) {
                    subject.getPrincipals().add(new RolePrincipal(role));
                }
                subject.setReadOnly();
                return _identityService.newUserIdentity(subject, userPrincipal, roles);
            }
        });

        return csh;
    }

    /**
     * @see org.overlord.commons.dev.server.DevServer#postStart(org.overlord.commons.dev.server.DevServerEnvironment)
     */
    @Override
    protected void postStart(DevServerEnvironment environment) throws Exception {
        System.out.println("----------  Seeding the Repository  ---------------");

        ArtificerAtomApiClient client = new ArtificerAtomApiClient(
                "http://localhost:" + serverPort() + "/artificer-server", "seeder", "seeder", true);

        String seedType = System.getProperty("artificer-dev-server.seed-type", "none");
        if ("switchyard".equals(seedType)) {
            doSwitchYardSeed(client);
        } else if ("standard".equals(seedType)) {
            doStandardSeed(client);
        } else {
            // no seeding
        }

        System.out.println("----------  DONE  ---------------");
        System.out.println("Now try:  \n  http://localhost:" + serverPort() + "/artificer-ui/index.html");
        System.out.println("---------------------------------");
    }

    /**
     * @param client
     * @throws org.artificer.atom.err.ArtificerAtomException
     * @throws org.artificer.client.ArtificerClientException
     */
    private void doStandardSeed(ArtificerAtomApiClient client)
            throws ArtificerClientException, ArtificerServerException {
        InputStream is = null;

        // Ontology #1
        try {
            is = ArtificerDevServer.class.getResourceAsStream("colors.owl.xml");
            client.uploadOntology(is);
            System.out.println("Ontology 1 added");
        } finally {
            IOUtils.closeQuietly(is);
        }

        // Ontology #2
        try {
            is = ArtificerDevServer.class.getResourceAsStream("regional.owl.xml");
            client.uploadOntology(is);
            System.out.println("Ontology 2 added");
        } finally {
            IOUtils.closeQuietly(is);
        }

        // PDF Document
        try {
            is = ArtificerDevServer.class.getResourceAsStream("sample.pdf");
            BaseArtifactType artifact = client.uploadArtifact(ArtifactType.Document(), is, "sample.pdf");
            artifact.setDescription(
                    "This is just a sample PDF file that is included in the dev server so that we have some content when we start up.");
            artifact.setVersion("1.0");
            client.updateArtifactMetaData(artifact);
            System.out.println("PDF added");
        } finally {
            IOUtils.closeQuietly(is);
        }

        // XML Document
        try {
            is = ArtificerDevServer.class.getResourceAsStream("order.xml");
            BaseArtifactType artifact = client.uploadArtifact(ArtifactType.XmlDocument(), is, "order.xml");
            artifact.getClassifiedBy().add("http://www.example.org/colors.owl#Blue");
            ArtificerModelUtils.setCustomProperty(artifact, "foo", "bar");
            ArtificerModelUtils.setCustomProperty(artifact, "angle", "obtuse");
            client.updateArtifactMetaData(artifact);
            System.out.println("XML file added");
        } finally {
            IOUtils.closeQuietly(is);
        }

        // WSDL Document
        try {
            is = ArtificerDevServer.class.getResourceAsStream("deriver.wsdl");
            BaseArtifactType artifact = client.uploadArtifact(ArtifactType.WsdlDocument(), is, "deriver.wsdl");
            artifact.getClassifiedBy().add("http://www.example.org/colors.owl#Red");
            artifact.getClassifiedBy().add("http://www.example.org/regional.owl#Asia");
            client.updateArtifactMetaData(artifact);
            System.out.println("WSDL added");
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

    /**
     * @param client
     */
    private void doSwitchYardSeed(ArtificerAtomApiClient client) throws Exception {
        // Upload the artifacts jar
        InputStream artifactsIS = this.getClass().getResourceAsStream("artifacts.jar");
        try {
            client.uploadArtifact(artifactsIS, "artifacts.jar");
            System.out.println("Added SwitchYard app (artifacts.jar)");
        } finally {
            IOUtils.closeQuietly(artifactsIS);
        }

        // Upload the order consumer jar
        InputStream orderConsumerIS = this.getClass().getResourceAsStream("order-consumer.jar");
        try {
            client.uploadArtifact(orderConsumerIS, "order-consumer.jar");
            System.out.println("Added SwitchYard app (order-consumer.jar)");
        } finally {
            IOUtils.closeQuietly(artifactsIS);
        }

        // Upload the order service jar
        InputStream orderServiceIS = this.getClass().getResourceAsStream("order-service.jar");
        try {
            client.uploadArtifact(orderServiceIS, "order-service.jar");
            System.out.println("Added SwitchYard app (order-service.jar)");
        } finally {
            IOUtils.closeQuietly(artifactsIS);
        }

    }

}