Package org.drools.guvnor.server.files

Source Code of org.drools.guvnor.server.files.RestAPI

/*
* Copyright 2010 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.drools.guvnor.server.files;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Properties;

import org.drools.guvnor.server.repository.Preferred;
import org.drools.repository.AssetHistoryIterator;
import org.drools.repository.AssetItem;
import org.drools.repository.ModuleItem;
import org.drools.repository.RulesRepository;
import org.drools.repository.RulesRepositoryException;
import org.drools.guvnor.server.files.Response;
import org.drools.guvnor.server.files.Response.Binary;
import org.drools.guvnor.server.files.Response.Text;
import org.drools.repository.utils.AssetValidator;
import org.drools.repository.utils.IOUtils;

import javax.inject.Inject;

/**
* This provides a simple REST style remote friendly API.
*/
public class RestAPI {

    @Inject @Preferred
    private RulesRepository rulesRepository;

    @Inject
    private AssetValidator assetValidator;


    private static Properties TEXT_ASSET_TYPES = loadAssetTypes();

    public RestAPI() {

    }
    public RestAPI(RulesRepository rulesRepository) {
        this.rulesRepository = rulesRepository;
    }

    private static Properties loadAssetTypes() {
        InputStream in = null;
        try {
            in = RestAPI.class.getResourceAsStream("text_assets.properties");
            Properties p = new Properties();
            p.load(in);
            return p;
        } catch (IOException e) {
            throw new IllegalStateException("Unable to load asset text types properties.", e);
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    /**
     * This works off:
     * packages/packageName --> returns list of : asset name=ISO date time last modified,versionNumber
     * packages/packageName/.package --> the contents of the package header
     * packages/packageName/assetName --> the contents of the package
     */
    public Response get(String path) throws UnsupportedEncodingException {
        String[] bits = split(path);
        if (bits.length == 1) return new Response.Text("");
        if (bits[0].equals("packages")) {
            String pkgName = bits[1];
            if (bits.length == 2) {
                return listPackage(pkgName);
            } else {
                String resourceFile = bits[2];
                return loadContent(pkgName, resourceFile);
            }
        } else {
            return new Response.Text("");//throw new IllegalArgumentException("Unable to deal with " + path);
        }

    }

    String[] split(String path) throws UnsupportedEncodingException {
        if (path.indexOf("api") > -1) {
            path = path.split("api")[1];
        }
        if (path.startsWith("/")) path = path.substring(1);
        String[] bits = path.split("/");
        for (int i = 0; i < bits.length; i++) {
            bits[i] = URLDecoder.decode(bits[i], "UTF-8");
        }
        return bits;
    }

    private Response loadContent(String pkgName, String resourceFile) throws UnsupportedEncodingException {
        ModuleItem pkg = rulesRepository.loadModule(pkgName);
        if (resourceFile.equals(".package")) {
            Text r = new Response.Text();
            r.lastModified = pkg.getLastModified();
            r.data = pkg.getStringProperty( ModuleItem.HEADER_PROPERTY_NAME );
            return r;
        } else {
            if (resourceFile.indexOf("?version=") > -1) {
                String[] v = resourceFile.split("\\?version\\=");
                String version = v[1];
                String assetName = AssetItem.getAssetNameFromFileName(v[0])[0];
                AssetItem asset = pkg.loadAsset(assetName);
                if (asset.isArchived()) {
                    Text r = new Text();
                    r.data = "";
                    return r;
                }
                if (version.equals("all")) {
                    AssetHistoryIterator it =  asset.getHistory();
                    StringBuilder buf = new StringBuilder();
                    while(it.hasNext()) {

                        AssetItem h = it.next();

                        if (h.getVersionNumber() != 0) {
                            String checkinComment = h.getCheckinComment();
                            //String lastMo ... hmm what is needed?
                            String lastMofiedBy = h.getLastContributor();
                            if (lastMofiedBy == null || lastMofiedBy.equals("")) {
                                lastMofiedBy = asset.getCreator();
                            }
                            SimpleDateFormat sdf = getISODateFormat();
                            Calendar lastModDate = h.getLastModified();
                            if (lastModDate == null ) {
                                lastModDate = asset.getCreatedDate();
                            }
                            String lastModifiedOn = sdf.format(lastModDate.getTime());
                            buf.append(h.getVersionNumber());
                            buf.append("=");
                            buf.append(lastModifiedOn + "," + lastMofiedBy + "," + checkinComment);
                            if (it.hasNext()) {
                                buf.append('\n');
                            }
                        }

                    }
                    Text r = new Text();
                    r.lastModified = asset.getLastModified();
                    r.data = buf.toString();
                    return r;
                } else {
                    long versionNumber = Long.parseLong(version);
                    AssetHistoryIterator it =  asset.getHistory();
                    while (it.hasNext()) {
                        AssetItem h = it.next();
                        if (h.getVersionNumber() == versionNumber) {
                            return buildAssetContentResponse(pkg, h);
                        }
                    }
                    //hmm... we didn't find it
                    Text r = new Text();
                    r.lastModified = asset.getLastModified();
                    r.data = "Unknown version number : " + versionNumber;
                    return r;
                }
            } else {
                 String assetName = AssetItem.getAssetNameFromFileName(resourceFile)[0];
                AssetItem asset = pkg.loadAsset(assetName);
                return buildAssetContentResponse(pkg, asset);
            }

        }

    }

    private Response buildAssetContentResponse(ModuleItem pkg, AssetItem asset) {
        if (asset.isBinary()) {
            Binary r = new Response.Binary();
            r.lastModified = asset.getLastModified();
            r.stream = asset.getBinaryContentAttachment();
            return r;
        } else {
            Text r = new Response.Text();
            r.lastModified = pkg.getLastModified();
            r.data = asset.getContent();
            return r;
        }
    }

    private Response listPackage(String pkgName) throws UnsupportedEncodingException {
        ModuleItem pkg = rulesRepository.loadModule(URLDecoder.decode(pkgName, "UTF-8"));
        StringBuilder sb = new StringBuilder();
        Iterator<AssetItem> it = pkg.getAssets();
        SimpleDateFormat sdf = getISODateFormat();

        while (it.hasNext()) {
            AssetItem a = it.next();
            if (!a.isArchived()) {
                Calendar lastMod = a.getLastModified();
                if (lastMod == null) {
                    lastMod = a.getCreatedDate();
                }
                sb.append(a.getName().replaceAll("\\s", "\\\\ ") + "." + a.getFormat() + "=" + sdf.format(lastMod.getTime()) + "," + a.getVersionNumber());
                sb.append('\n');
            }
        }

        Text r = new Response.Text();
        r.lastModified = pkg.getLastModified();
        r.data = sb.toString();
        return r;
    }

    private String escapeSpacesForProps(String s) {
        return s.replaceAll("\\s", "\\ ");
    }

    /**
     * This is the format used to sent dates as text, always.
     */
    public static SimpleDateFormat getISODateFormat() {
        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    }

    /** post is for new content.
     * @throws IOException
     * @throws RulesRepositoryException */
    public void post(String path, InputStream in, String comment) throws RulesRepositoryException, IOException {
        String[] bits = split(path);
        if (bits[0].equals("packages")) {
            String fileName = bits[2];
            String[] a = fileName.split("\\.");
            if (a[1].equals("package")) {
                //new package
                ModuleItem pkg = rulesRepository.createModule(bits[1], "<added remotely>");
                pkg.updateCheckinComment(comment);
                pkg.updateStringProperty(readContent(in), ModuleItem.HEADER_PROPERTY_NAME);
                rulesRepository.save();
            } else {
                //new asset
                ModuleItem pkg = rulesRepository.loadModule(bits[1]);
                AssetItem asset;
                if (pkg.containsAsset(a[0])) {
                    asset = pkg.loadAsset(a[0]);
                    if (asset.isArchived()) {
                        asset.archiveItem(false);
                    } else {
                        throw new RulesRepositoryException("The file " + path + " already exists, and was not archived.");
                    }
                    if (asset.isBinary()) {
                        asset.updateBinaryContentAttachment(in);
                    } else {
                        asset.updateContent(readContent(in));
                    }
                } else {
                    asset = pkg.addAsset(a[0], "<added remotely>");
                    asset.updateFormat(a[1]);
                    if (TEXT_ASSET_TYPES.containsKey(a[1])) {
                        asset.updateContent(readContent(in));
                    } else {
                        asset.updateBinaryContentAttachment(in);
                    }
                }
                asset.updateValid(assetValidator.validate(asset));
                asset.checkin(comment);
            }
        } else {
            throw new IllegalArgumentException("Unknown rest path for post.");
        }
    }

    private String readContent(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        final byte[] buf = new byte[1024];
        int len = 0;
        while ( (len = in.read( buf )) >= 0 ) {
            out.write( buf,
                       0,
                       len );
        }
        return new String(out.toByteArray());
    }

    /**
     * Put is for updating content. It will cause a new revision to be created.
     * need to also cope with the .package thing
     * @throws IOException
     */
    public void put(String path, Calendar lastModified, InputStream in, String comment) throws IOException {
        String[] bits = split(path);
        if (bits[0].equals("packages")) {
            String fileName = bits[2];
            String[] a = fileName.split("\\.");
            ModuleItem pkg = rulesRepository.loadModule(bits[1]);
            if (a[1].equals("package")) {
                //updating package header
                if (lastModified != null && pkg.getLastModified().after(lastModified)) {
                    throw new RulesRepositoryException("The package was modified by: " + pkg.getLastContributor() + ", unable to write changes.");
                }
                pkg.updateStringProperty(readContent(in), ModuleItem.HEADER_PROPERTY_NAME);
                pkg.checkin(comment);
                rulesRepository.save();
            } else {
                AssetItem as = pkg.loadAsset(a[0]);
                if (lastModified != null && as.getLastModified().after(lastModified)) {
                    throw new RulesRepositoryException("The asset was modified by: " + as.getLastContributor() + ", unable to write changes.");
                }
                if (as.isBinary()) {
                    as.updateBinaryContentAttachment(in);
                } else {
                    as.updateContent(readContent(in));
                }
                as.updateValid(assetValidator.validate(as));
                as.checkin(comment);
            }

        } else {
            throw new IllegalArgumentException("Unknown rest path for put");
        }

    }

    /**
     * Should be pretty obvious what this is for.
     * @throws UnsupportedEncodingException
     */
    public void delete(String path) throws UnsupportedEncodingException {
        String[] bits = split(path);
        if (bits[0].equals("packages")) {
            String fileName = bits[2].split("\\.")[0];
            AssetItem asset = rulesRepository.loadModule(bits[1]).loadAsset(fileName);
            asset.archiveItem(true);
            asset.checkin("<removed remotely>");
        }
        else {
            throw new IllegalArgumentException("Unknown rest path for delete");
        }

    }

    public AssetValidator getAssetValidator() {
        return assetValidator;
    }

    public void setAssetValidator(AssetValidator assetValidator) {
        this.assetValidator = assetValidator;
    }




}
TOP

Related Classes of org.drools.guvnor.server.files.RestAPI

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.