Package org.drools.repository.remoteapi

Source Code of org.drools.repository.remoteapi.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.repository.remoteapi;

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.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

import org.drools.repository.AssetHistoryIterator;
import org.drools.repository.AssetItem;
import org.drools.repository.PackageItem;
import org.drools.repository.RulesRepository;
import org.drools.repository.RulesRepositoryException;
import org.drools.repository.remoteapi.Response.Binary;
import org.drools.repository.remoteapi.Response.Text;
import org.drools.repository.utils.IOUtils;

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

  private final RulesRepository repo;

  private static Properties TEXT_ASSET_TYPES = loadAssetTypes();

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

  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 {
    PackageItem pkg = repo.loadPackage(pkgName);
    if (resourceFile.equals(".package")) {
      Text r = new Response.Text();
      r.lastModified = pkg.getLastModified();
      r.data = pkg.getStringProperty( PackageItem.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(PackageItem 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 {
    PackageItem pkg = repo.loadPackage(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
        PackageItem pkg = repo.createPackage(bits[1], "<added remotely>");
        pkg.updateCheckinComment(comment);
        pkg.updateStringProperty(readContent(in), PackageItem.HEADER_PROPERTY_NAME);
        repo.save();
      } else {
        //new asset
        PackageItem pkg = repo.loadPackage(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.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("\\.");
      PackageItem pkg = repo.loadPackage(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), PackageItem.HEADER_PROPERTY_NAME);
        pkg.checkin(comment);
        repo.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.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 = repo.loadPackage(bits[1]).loadAsset(fileName);
      asset.archiveItem(true);
      asset.checkin("<removed remotely>");
    }
    else {
      throw new IllegalArgumentException("Unknown rest path for delete");
    }

  }



}
TOP

Related Classes of org.drools.repository.remoteapi.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.