Java tutorial
/* * Copyright (c) 2014 3 Round Stones Inc., Some Rights Reserved * * 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.callimachusproject.setup; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.http.HttpHost; import org.apache.http.client.utils.URIUtils; import org.callimachusproject.client.HttpClientFactory; import org.callimachusproject.client.UnavailableRequestDirector; import org.callimachusproject.engine.model.TermFactory; import org.callimachusproject.repository.CalliRepository; import org.callimachusproject.repository.auditing.AuditingRepositoryConnection; import org.openrdf.OpenRDFException; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.ValueFactory; import org.openrdf.model.vocabulary.RDF; import org.openrdf.model.vocabulary.RDFS; import org.openrdf.repository.DelegatingRepositoryConnection; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; import org.openrdf.repository.RepositoryResult; import org.openrdf.repository.object.ObjectConnection; import org.openrdf.repository.object.RDFObject; import org.openrdf.repository.object.exceptions.RDFObjectException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class WebappArchiveImporter { private static final String GROUP_PUBLIC = "/auth/groups/public"; private static final String GROUP_SUPER = "/auth/groups/super"; private static final String SCHEMA_GRAPH = "types/RdfSchemaGraph"; private static final String REALM_TYPE = "types/Realm"; private static final String ORIGIN_TYPE = "types/Origin"; private static final String FOLDER_TYPE = "types/Folder"; private static final String CALLI = "http://callimachusproject.org/rdf/2009/framework#"; private static final String CALLI_READER = CALLI + "reader"; private static final String CALLI_FOLDER = CALLI + "Folder"; private static final String CALLI_HASCOMPONENT = CALLI + "hasComponent"; private static final String CALLI_ADMINISTRATOR = CALLI + "administrator"; private final Logger logger = LoggerFactory.getLogger(WebappArchiveImporter.class); private final String webapp; private final CalliRepository repository; private URI[] schemaGraphs; public WebappArchiveImporter(String webapp, CalliRepository repository) { this.webapp = webapp; this.repository = repository; } public void setSchemaGraphs(URI... schemaGraphs) { this.schemaGraphs = schemaGraphs; } public void importArchive(InputStream carStream, String folder) throws IOException, OpenRDFException, NoSuchMethodException, InvocationTargetException { createFolder(folder, webapp, repository); importArchive(carStream, folder, webapp, repository); } public void removeFolder(String folder) { deleteComponents(folder); } protected void setFolderPermissions(URI uri, ObjectConnection con) throws RepositoryException { TermFactory tf = TermFactory.newInstance(webapp); add(con, uri, CALLI_READER, tf.resolve(GROUP_PUBLIC)); add(con, uri, CALLI_ADMINISTRATOR, tf.resolve(GROUP_SUPER)); } private void importArchive(InputStream carStream, String folderUri, String webapp, CalliRepository repository) throws IOException, OpenRDFException, NoSuchMethodException, InvocationTargetException { HttpHost host = URIUtils.extractHost(java.net.URI.create(webapp)); UnavailableRequestDirector service = new UnavailableRequestDirector(); HttpClientFactory.getInstance().setProxyIfAbsent(host, service); try { if (schemaGraphs != null) { for (URI schemaGraph : schemaGraphs) { repository.addSchemaGraph(schemaGraph); } } else { repository.setSchemaGraphType(webapp + SCHEMA_GRAPH); } repository.setCompileRepository(true); ObjectConnection con = repository.getConnection(); try { disableAuditingRemoval(con); con.begin(); if (schemaGraphs != null && schemaGraphs.length > 0) { con.clear(schemaGraphs); } Object folder = con.getObject(folderUri); Method UploadFolderComponents = findUploadFolderComponents(folder); try { logger.info("Importing {}", folderUri); int argc = UploadFolderComponents.getParameterTypes().length; Object[] args = new Object[argc]; args[0] = carStream; UploadFolderComponents.invoke(folder, args); } catch (IllegalAccessException e) { throw new AssertionError(e); } repository.setCompileRepository(false); con.commit(); } finally { con.close(); HttpClientFactory.getInstance().removeProxy(host, service); } } finally { repository.setCompileRepository(false); if (schemaGraphs != null) { for (URI schemaGraph : schemaGraphs) { repository.removeSchemaGraph(schemaGraph); } } } } private boolean disableAuditingRemoval(RepositoryConnection con) throws RepositoryException { if (con instanceof AuditingRepositoryConnection) { ((AuditingRepositoryConnection) con).setAuditingRemoval(false); return true; } if (con instanceof DelegatingRepositoryConnection) return disableAuditingRemoval(((DelegatingRepositoryConnection) con).getDelegate()); return false; } private Method findUploadFolderComponents(Object folder) throws NoSuchMethodException { for (Method method : folder.getClass().getMethods()) { if ("UploadFolderComponents".equals(method.getName())) return method; } throw new NoSuchMethodException("UploadFolderComponents"); } private void createFolder(String folder, String webapp, CalliRepository repository) throws OpenRDFException { String parent = getParentFolder(folder); if (parent != null) { createFolder(parent, webapp, repository); } ValueFactory vf = repository.getValueFactory(); ObjectConnection con = repository.getConnection(); try { URI uri = vf.createURI(folder); if (parent == null) { RepositoryResult<Statement> stmts = con.getStatements(uri, RDF.TYPE, null); try { while (stmts.hasNext()) { Statement st = stmts.next(); String type = st.getObject().stringValue(); if (type.endsWith(ORIGIN_TYPE) || type.endsWith(REALM_TYPE) || type.endsWith(FOLDER_TYPE)) { return; } } } finally { stmts.close(); } throw new IllegalStateException( "Can only import a CAR within a previously defined origin or realm"); } else { if (con.hasStatement(uri, RDF.TYPE, vf.createURI(webapp + ORIGIN_TYPE))) return; if (con.hasStatement(uri, RDF.TYPE, vf.createURI(webapp + REALM_TYPE))) return; if (con.hasStatement(uri, RDF.TYPE, vf.createURI(webapp + FOLDER_TYPE))) return; if (con.hasStatement(vf.createURI(parent), vf.createURI(CALLI_HASCOMPONENT), uri)) return; con.begin(); con.add(vf.createURI(parent), vf.createURI(CALLI_HASCOMPONENT), uri); String label = folder.substring(parent.length()).replace("/", "").replace('-', ' '); con.add(uri, RDF.TYPE, vf.createURI(CALLI_FOLDER)); con.add(uri, RDF.TYPE, vf.createURI(webapp + FOLDER_TYPE)); con.add(uri, RDFS.LABEL, vf.createLiteral(label)); setFolderPermissions(uri, con); con.commit(); return; } } finally { con.close(); } } private String getParentFolder(String folder) { int idx = folder.lastIndexOf('/', folder.length() - 2); if (idx < 0) return null; String parent = folder.substring(0, idx + 1); if (parent.endsWith("://")) return null; return parent; } private void add(ObjectConnection con, URI subj, String pred, String resource) throws RepositoryException { ValueFactory vf = con.getValueFactory(); con.add(subj, vf.createURI(pred), vf.createURI(resource)); } private boolean deleteComponents(String folder) { try { try { repository.setSchemaGraphType(webapp + SCHEMA_GRAPH); repository.setCompileRepository(true); ObjectConnection con = repository.getConnection(); try { con.begin(); RDFObject obj = (RDFObject) con.getObject(folder); Method DeleteComponents = findDeleteComponents(obj); try { logger.info("Removing {}", folder); invokeAndRemove(DeleteComponents, obj, con); con.commit(); return true; } catch (InvocationTargetException e) { try { throw e.getCause(); } catch (Exception cause) { logger.warn(cause.toString()); } catch (Error cause) { logger.warn(cause.toString()); } catch (Throwable cause) { logger.warn(cause.toString()); } con.rollback(); return false; } } catch (IllegalAccessException e) { logger.debug(e.toString()); } catch (NoSuchMethodException e) { logger.debug(e.toString()); } finally { con.rollback(); repository.setCompileRepository(false); con.close(); } } finally { repository.setCompileRepository(false); } } catch (RDFObjectException e) { logger.debug(e.toString()); } catch (OpenRDFException e) { logger.debug(e.toString()); } return false; } private Method findDeleteComponents(Object folder) throws NoSuchMethodException { for (Method method : folder.getClass().getMethods()) { if ("DeleteComponents".equals(method.getName())) return method; } throw new NoSuchMethodException("DeleteComponents in " + folder); } private void invokeAndRemove(Method DeleteComponents, RDFObject folder, ObjectConnection con) throws IllegalAccessException, InvocationTargetException, OpenRDFException { int argc = DeleteComponents.getParameterTypes().length; DeleteComponents.invoke(folder, new Object[argc]); Resource target = folder.getResource(); ValueFactory vf = con.getValueFactory(); String parent = getParentFolder(target.stringValue()); if (parent != null) { con.remove(vf.createURI(parent), null, target); } con.remove(target, null, null); } }