Package com.dbxml.labrador.rest

Source Code of com.dbxml.labrador.rest.RESTHandler

package com.dbxml.labrador.rest;

/*
* The dbXML Labrador Software License, Version 1.0
*
*
* Copyright (c) 2003 The dbXML Group, L.L.C.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by The
*        dbXML Group, L.L.C. (http://www.dbxml.com/)."
*    Alternately, this acknowledgment may appear in the software
*    itself, if and wherever such third-party acknowledgments normally
*    appear.
*
* 4. The names "Labrador" and "dbXML Group" must not be used to
*    endorse or promote products derived from this software without
*    prior written permission. For written permission, please contact
*    info@dbxml.com
*
* 5. Products derived from this software may not be called "Labrador",
*    nor may "Labrador" appear in their name, without prior written
*    permission of The dbXML Group, L.L.C..
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE DBXML GROUP, L.L.C. OR ITS
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* $Id: RESTHandler.java,v 1.32 2003/12/14 05:17:57 bradford Exp $
*/

import com.dbxml.labrador.*;
import java.io.*;

import com.dbxml.labrador.broker.Broker;
import com.dbxml.labrador.broker.BrokerContext;
import com.dbxml.labrador.configuration.Configuration;
import com.dbxml.labrador.configuration.ConfigurationCallback;
import com.dbxml.labrador.configuration.ConfigurationException;
import com.dbxml.labrador.exceptions.RequestException;
import com.dbxml.labrador.http.HTTP;
import com.dbxml.labrador.types.ArrayConversions;
import com.dbxml.labrador.types.Types;
import com.dbxml.labrador.types.Variant;
import com.dbxml.labrador.util.SimpleConfigurable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.bind.Element;
import org.w3c.dom.Node;

/**
* RESTHandler
*/

public final class RESTHandler extends SimpleConfigurable implements Handler {
   private static final int BUFFER_SIZE = 8192;

   private static final String PROTOCOL = "REST";

   public static final String PREFIX = "/rest/";

   public static final String CONTENT_TYPE = "REST_CONTENT_TYPE";
   public static final String DEFAULT_METHOD = "REST_DEFAULT_METHOD";

   private static final String METHOD = "method";

   private static final String MIMEMAPPINGS = "mime-mappings";
   private static final String MIMEMAPPING = "mime-mapping";
   private static final String EXT = "ext";
   private static final String TYPE = "type";

   private Map mimeTypes = new HashMap();

   public RESTHandler() {
   }

   public String getProtocol() {
      return PROTOCOL;
   }

   public boolean isRequestValid(Request request) {
      return request.getPath().startsWith(PREFIX);
   }

   public ID getInstanceID(Request request) {
      return new ID(request.getPath().substring(PREFIX.length() - 1));
   }

   public void setConfig(Configuration config) throws ConfigurationException {
      super.setConfig(config);
      Configuration mimeCfg = config.getChild(MIMEMAPPINGS);
      if ( mimeCfg != null ) {
         mimeCfg.processChildren(MIMEMAPPING, new ConfigurationCallback() {
            public void process(Configuration cfg) {
               String ext = cfg.getAttribute(EXT);
               String type = cfg.getAttribute(TYPE);
               mimeTypes.put(ext, type);
            }
         });
      }
   }

   private String getMimeType(ID id) {
      String path = id.toString();
      int idx = path.lastIndexOf('.');
      if ( idx != -1 ) {
         String ext = path.substring(idx + 1);
         return (String)mimeTypes.get(ext);
      }
      return null;
   }

   private void writeValue(OutputStream os, Object o) throws IOException {
      if ( o != null && o.getClass().isArray() )
         writeArray(os, o);
      else
         writeVariant(os, new Variant(o));
   }

   private void writeValue(PrintWriter pw, Object o) throws IOException {
      if ( o != null && o.getClass().isArray() )
         writeArray(pw, o);
      else
         writeVariant(pw, new Variant(o));
   }

   private void writeArray(OutputStream os, Object o) throws IOException {
      if ( o instanceof byte[] ) {
         byte[] b = (byte[])o;
         os.write(b);
      }
      else {
         List l = ArrayConversions.toList(o);
         writeVariant(os, new Variant(l));
      }
   }

   private void writeArray(PrintWriter pw, Object o) throws IOException {
      if ( o instanceof byte[] ) {
         byte[] b = (byte[])o;
         pw.write(new String(b));
      }
      else {
         List l = ArrayConversions.toList(o);
         writeVariant(pw, new Variant(l));
      }
   }

   private void writeVariant(PrintWriter pw, Variant v) throws IOException {
      if ( v.isNull() )
         return;

      switch ( v.getType() ) {
         case Types.VOID:
         case Types.EMPTY:
            break;

         case Types.BOOLEAN:
         case Types.BYTE:
         case Types.SHORT:
         case Types.INT:
         case Types.LONG:
         case Types.DOUBLE:
         case Types.FLOAT:
         case Types.STRING:
         case Types.CHAR:
         case Types.NODE:
         case Types.DATE:
            pw.println(v.toString());
            break;

         case Types.LIST:
            Iterator l = v.getList().iterator();
            while ( l.hasNext() )
               writeVariant(pw, new Variant(l.next()));
            break;

         case Types.MAP:
            Map m = v.getMap();
            Iterator k = m.keySet().iterator();
            while ( k.hasNext() ) {
               Object key = k.next();
               pw.print(key + "=");
               writeVariant(pw, new Variant(m.get(key)));
            }
            break;

         case Types.OBJECT:
            writeValue(pw, v.getObject());
            break;
      }
   }

   private void writeVariant(OutputStream os, Variant v) throws IOException {
      OutputStreamWriter osw = new OutputStreamWriter(os, "UTF8");
      BufferedWriter bw = new BufferedWriter(osw, 4096);
      PrintWriter pw = new PrintWriter(bw);
      writeVariant(pw, v);
      pw.flush();
   }

   public void processRequest(Request request, Response response, Instance instance) throws RequestException {
      String methodName = request.getValue(METHOD);
      if ( methodName == null || methodName.length() == 0 ) {
         Object val = instance.getProperty(DEFAULT_METHOD);
         if ( val instanceof String )
            methodName = (String)val;
         else
            throw new RequestException("No method name was set");
      }
      instance.setMethodName(methodName);

      BrokerContext context = Broker.getInstance().getBrokerContext();
      Discovery disc = context.getDiscovery();
      String[] paramNames = disc.listParams(methodName);
      boolean postUsed = false;

      for ( int i = 0; paramNames != null && i < paramNames.length; i++ ) {
         boolean array = disc.isParamArray(methodName, i);
         String[] vals = request.getValues(paramNames[i]);

         if ( vals != null ) {
            if ( array )
               instance.setParameter(i, vals);
            else
               instance.setParameter(i, vals[0]);
         }
         else if ( !postUsed && request.hasContent() ) {
            // If there is POST data, and this parameter is a String, Document,
            // or byte array, then let us assume that the POST data is intended
            // for this one.
            try {
               InputStream is = request.getInputStream();
               ByteArrayOutputStream bos = new ByteArrayOutputStream(BUFFER_SIZE);

               byte[] buffer = new byte[BUFFER_SIZE];
               int size;
               do {
                  size = is.read(buffer);
                  if ( size > 0 )
                     bos.write(buffer, 0, size);
               }
               while ( size != -1 );

               instance.setParameter(i, bos.toByteArray());
               postUsed = true;
            }
            catch ( IOException e ) {
               /** @todo Hmmm */
            }
         }
         else
            instance.setParameter(i, null);
      }

      // Initially set the MIME type in case we get an HTTP 403 Exception
      ID id = context.getId();

      String contentType = getMimeType(id);
      if ( contentType != null )
         response.setHeader(HTTP.HEADER_CONTENT_TYPE, contentType);

      Object o = instance.invoke();

      Object type = context.getProperty(CONTENT_TYPE);
      if ( type == null )
         type = instance.getProperty(CONTENT_TYPE+'_'+methodName);

      if ( type instanceof String ) {
         contentType = (String)type;
         response.setHeader(HTTP.HEADER_CONTENT_TYPE, contentType);
      }

      if ( contentType == null ) {
         if ( o instanceof Node || o instanceof Element )
            contentType = Headers.TYPE_TEXT_XML;
         else
            contentType = Headers.TYPE_TEXT_PLAIN;
         response.setHeader(HTTP.HEADER_CONTENT_TYPE, contentType);
      }

      try {
         OutputStream os = response.getOutputStream();
         writeValue(os, o);
         os.flush(); // Is this needed?
         os.close(); // Is this needed?
         response.close();
      }
      catch ( IOException e ) {
         throw new RequestException(e.getMessage());
      }
   }

   public void processError(Response response, String code, String message) {
      // NOOP
   }
}



TOP

Related Classes of com.dbxml.labrador.rest.RESTHandler

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.