⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 z39lsp.java

📁 数字图书馆的互操作接口
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
	  return;

	// add header for GServer.
	//	    if (gservResource != null)
	//	        System.arraycopy(gservResource, 0, req.record(), 0,
	//		    gservLength);
	pendingRequests++;
	try {
	  client.init.Response(((BerConnect)client.connection).doRequest(req, client.host, client.port));
	} catch (Exception e) {
	  pendingRequests--;
	  client.reset();
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Could not initialize " + client.host + ":" + client.port + ": " + e.getMessage());
	}
	pendingRequests--;
	//            System.out.println("Done with Init request");
	//	    if (client.init.MessageOfTheDay != null)
	//		System.out.println(client.init.MessageOfTheDay);

	switch (client.init.failureCode) {

	case Z39presentApi.success: // valid init

	  createSubcollectionInfo();
	  break;

	case Z39initApi.InvalidAutho:
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Init failure: Invalid Autho");

	case Z39initApi.BadAuthoPassword:
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Init failure: Unmatched authorization/password");

	case Z39initApi.NoSearchesRemaining:
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Init failure: No Searches remaining for the autho");

	case Z39initApi.IncorrectInterfaceType:
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Init failure: Autho has incorrect interface type");

	case Z39initApi.MaxNumberSimultaneousUsers:
	throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Init failure: Max Number Simultaneous Users for the autho");

	case Z39initApi.BlockedIPAddress:
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Init failure: Blocked IP Address");

	default:
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Init failure: Unknown Z39.50 reason code = '" +
				   client.init.failureCode + "'");
	}

	/*
	  if (client.init.failureCode != 0)
	  return false;

	  CanDoScan = true;

	  if (client.init.options.length() > 7 &&
	  client.init.options.charAt(7) == 'y') {
	  }
	  else
	  System.out.println(
	"This server indicates that it does NOT support the Scan Facility");
	*/
	//lsp.dbg.println(DBG.SHORT, "Session established to " + lsp.host + ":" + lsp.port);
      }

      if(query == null) // collect metadata only
	return;

      if(!searchAttempted) {
	// run the query
	searchAttempted = true;
	//lsp.dbg.println(DBG.SHORT, "Running query " + query);

	//if(lsp.defaultSubcol == null)
	//  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Internal error: no default subcollection specified!");

	pendingRequests++;
	BerString req = client.search.Request(0, 0,
            	    1, 0,
		    1, "default", lsp.defaultSubcol,
		    null, null, lsp.preferredRecordSyntax, query, lsp.queryType,
		    null, null, null, "1.2.840.10003.10.1000.17.7",
		    null, null, gservLength, gservLength);
	pendingRequests--;

	if (req == null)
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Internal error: query translation failed.");

	//		if (gservResource != null)
	//		    System.arraycopy(gservResource, 0, req.record(), 0,
	//			gservLength);
	pendingRequests++;
	try {
	  client.search.Response(((BerConnect)client.connection).doRequest(req, client.host, client.port));
	} catch (AccessControl aa) {
	  pendingRequests--;
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Access denied.");
	} catch (Exception e) {
	  client.reset();
	  pendingRequests--;
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Search failed: " + e.getMessage());
	}
	pendingRequests--;
	/*
	if (client.search.searchStatus == 0 &&
		    client.search.errorCode == 107 &&
		    query_type == 101)
		{
		    System.out.println("Query Type101 not support by server. "
			+ " Degrading to Type1 and retrying. ");
		    System.out.println("All future queries will be of Type1.");
		    query_type = 1;
		    return true;
		}
		*/
	if (client.search.searchStatus != 0 /*|| client.search.errorCode == 12 partial results*/) {
	  //lsp.dbg.println(DBG.SHORT, "Search successful");
	  addRecords(1, client.search.Present);
	} else {
	  throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Search failed: Z39.50 error code = " + client.search.errorCode +
				   ", message = " + client.search.errorMsg);
	}
      }
    }

    public String toString() {
      return "[SID:" + SID + "]";
    }
  }

  static final int DEFAULT_Z3950_PORT = 210;
  static final int MAX_STATE_TIMEOUT = 10 * 60; // 10 min
  static final int MAX_DOCS_PER_FETCH = 100;

  Hashtable sessions = new Hashtable(); // Integer -> Session
  int lastSessionID = 0;

  String host;
  int port;

  XMLObject subcolInfo;
  String defaultSubcol;

  String preferredRecordSyntax = Z39presentApi.MARC_SYNTAX;
  int queryType = 1;

  public Z39LSP(String hostPort) throws DLI2FEException {
    try {
      // extract host and port, misuse URL for that
      URL lspURI = new URL("http://" + hostPort);
      host = lspURI.getHost();
      port = lspURI.getPort();
      if(port <= 0)
	port = DEFAULT_Z3950_PORT;
    } catch (MalformedURLException mue) {
      throw new DLI2FEException(DLI2FEException.SERVER_ERROR_EXC, "Invalid Z39.50 server access point: " + hostPort);
    }
  }

  public void setDefaultSubcol(String subcol) {
    defaultSubcol = subcol;
  }

  public void getSiteMetadata (dli2fe.XMLObject theSiteMetadata) throws DLI2FEException {
    collectMetadata();

    if(this.subcolInfo == null)
      throw new DLI2FEException(DLI2FEException.NOT_IMPLEMENTED_EXC, "");
    else
      XMLObject.setElement(theSiteMetadata, subcolInfo.getElement());
  }

  public void getAttributeInfo (String ctgrName,
                                dli2fe.XMLObject attributeInfo) throws DLI2FEException {
  }

  public void search(
		     int clientSID,
		     dli2fe.XMLObject subcollections,
		     dli2fe.XMLObject query,
		     int numDocs,
		     dli2fe.XMLObject docProps,
		     dli2fe.XMLObject queryOptions,
		     IntHolder expectedTotal,
		     IntHolder serverSID,
		     dli2fe.XMLObject result
		     )
    throws DLI2FEException {


    /* get Elements from anonymous XMLObjects */
    Element eQuery = XMLObject.create(query).getElement();

    Element eWhere = DOMUtil.getChild(eQuery, DAV.where);
    Element queryBody = QueryUtil.inside(eWhere);

    String rpnQuery = null;

    // case 1: simple "contains" query

    String containsStr = DOMUtil.getDescendantText(eWhere, DAV.contains);
    if(containsStr != null) {
      rpnQuery =
	enquote(containsStr) + "/u=4 " +
	enquote(containsStr) + "/u=62 OR " +
	enquote(containsStr) + "/u=1003 OR";
    } else {
      // complex query
      queryBody = QueryUtil.canonicalDNF(queryBody);
      if(QueryUtil.isTrue(queryBody))
	throw new DLI2FEException(DLI2FEException.BAD_QUERY_EXC, "Query is always true!");
      if(QueryUtil.isFalse(queryBody)) {
	// empty set
	expectedTotal.value = 0;
	result.setString("<SearchResult xmlns='" + DLI2FE.Namespace + "'/>");
	return;
      }
      rpnQuery = getRPNQuery(queryBody);
    }

    System.out.println("--- RPN query: " + rpnQuery);

    // create a new session
    Session session = new Session(++lastSessionID, rpnQuery, this);

    // stateful request, save the new session
    addSession(session);
    String docSelection = (numDocs == dli2fe.Searcher.RETURN_ALL_DOCS) ? "1-" : "1-" + numDocs;

    /* deliver the result */
    XMLObject.setElement(result, session.getDocs(docSelection, docProps));
    // set expected total number of results
    expectedTotal.value = session.getNumDocs();
    // set timeout after request processing for more accurate result
    serverSID.value = session.getSID();
  }

  String getRPNQuery(Element op) throws DLI2FEException {

    String orSubQuery = null;

    NodeList orList = DOMUtil.getChildElements(op, "*");
    for(int i=0; i < orList.getLength(); i++) {
      NodeList andList = DOMUtil.getChildElements((Element)orList.item(i), "*");
      String andSubQuery = null;
      // separate negated and non-negated operands
      Vector nonneg = new Vector();
      Vector neg = new Vector();
      for(int j=0; j < andList.getLength(); j++) {
	Element predicate = (Element)andList.item(j);
	if(QueryUtil.isNOT(predicate))
	  neg.addElement(predicate);
	else
	  nonneg.addElement(predicate);
      }
      // if there are no positive operands, throw an error
      if(nonneg.size() == 0)
	throw new DLI2FEException(DLI2FEException.BAD_QUERY_EXC, "Unbound operand(s) in the query, cannot replace with AND-NOT");
      // process non-negative
      for(int k = 0; k < nonneg.size(); k++) {
	Element predicate = (Element)nonneg.elementAt(k);
	String res = getRPNPredicate(predicate);
	if(andSubQuery == null)
	  andSubQuery = res;
	else
	  andSubQuery += " " + res + " AND";
      }
      // process negative
      for(int k = 0; k < neg.size(); k++) {
	Element predicate = (Element)neg.elementAt(k);
	andSubQuery += " " + getRPNPredicate(QueryUtil.inside(predicate)) + " NOT";
      }
      if(orSubQuery == null)
	orSubQuery = andSubQuery;
      else
	orSubQuery += " " + andSubQuery + " OR";
    }

    return orSubQuery;
  }

  String getRPNPredicate(Element op) throws DLI2FEException {

    Element eProp = QueryUtil.inside(DOMUtil.getChild(op, DAV.prop));
    String value = DOMUtil.getChildText(op, DAV.literal);
    if(eProp == null || value == null)
      throw new DLI2FEException(DLI2FEException.BAD_QUERY_EXC, "Malformed operand: " + op.getTagName());
    String tag = eProp.getLocalName();

    String s = null;

    if(DublinCore.Title.equals(tag))
      s = enquote(value) + "/u=4";
    else if(DublinCore.Creator.equals(tag))
      s = enquote(value) + "/u=1003";
    else if(DublinCore.Description.equals(tag))
      s = enquote(value) + "/u=62";
    else if(DublinCore.Subject.equals(tag))
      s = enquote(value) + "/u=21";
    else
      throw new DLI2FEException(DLI2FEException.BAD_QUERY_EXC, "Unsupported operator: " + tag);
    return s;
  }

  String enquote(String s) {
    if(s.indexOf('"') >= 0)
      return s;
    else
      return "\"" + s + "\"";
  }

  /* Method of Timeoutable */
  /*
  public void timeout(Object handle) {

    Session session = (Session)handle;
    dbg.println(DBG.SHORT, "Session " + session + " timed out!");
    removeSession(session);
  }
  */

  /* Methods of the source metadata interface */


  public void getInterface(dli2fe.XMLObject intf) throws DLI2FEException {

    collectMetadata();
    intf.setString("");
  }

  public void getSubcollectionInfo(dli2fe.XMLObject subcolInfo) throws DLI2FEException {

    collectMetadata();
    if(this.subcolInfo == null)
      throw new DLI2FEException(DLI2FEException.NOT_IMPLEMENTED_EXC, "");
    else
      XMLObject.setElement(subcolInfo, this.subcolInfo.getElement());
  }

  public void setSubcollectionInfo(dli2fe.XMLObject subcolInfo) throws DLI2FEException {

    this.subcolInfo = XMLObject.create(subcolInfo);
  }


  boolean isMetadataCollected = false;

  synchronized void collectMetadata() throws DLI2FEException {

    if(subcolInfo != null || isMetadataCollected)
      return;
    isMetadataCollected = true;

    Session session = new Session(0, null, this);
    session.initialize();
    session.cancel();
  }

  public void getPropertyInfo(String subcolName,
			      dli2fe.XMLObject propInfo) throws DLI2FEException {

      propInfo.setString("<propList xmlns='" + DLI2FE.Namespace + "'" +
			 "          xmlns:dc='" + DublinCore.Namespace + "'>" +
			 "  <dc:Title><searchable/><retrievable/></dc:Title>" +
			 "  <dc:Creator><searchable/><retrievable/></dc:Creator>" +
			 "  <dc:Description><searchable/><retrievable/></dc:Description>" +
			 "</propList>");
  }

  // Methods of the ResultAccess interface

  // ResultAccess implementation

  public void cancelRequest(int serverSID, int reqID)
    throws DLI2FEException {

    // we can only cancel the whole session ;(
    Session s = findSession(serverSID);
    //dbg.println(DBG.SHORT, "Cancelling session " + s);
    s.cancel();
    if(reqID == ResultAccess.CANCEL_ALL_REQUESTS) {
      removeSession(s);
    }
  }

  public void getSessionInfo(
			     int serverSID,
			     IntHolder expectedTotal,
			     IntHolder stateTimeout
			     )
    throws DLI2FEException {


    Session session = findSession(serverSID);
    expectedTotal.value = session.getNumDocs();
    stateTimeout.value = session.getTimeout();
    //dbg.println(DBG.SHORT, "Info requested for " + session + ": total=" + expectedTotal.value + ", timeout=" + stateTimeout.value);
  }

  public void getDocs(
		      int serverSID,
		      int reqID,
		      dli2fe.XMLObject docPropList,
		      String docsToGet,
		      dli2fe.XMLObject res )
    throws DLI2FEException {

    Session session = findSession(serverSID);
    //dbg.println(DBG.SHORT, "Getting documents " + docsToGet + " for " + session);
    XMLObject.setElement(res, session.getDocs(docsToGet, docPropList));
  }

  public void extendStateTimeout(int serverSID,
				 int additionalTime )
    throws DLI2FEException {

    Session session = findSession(serverSID);
    // it can happen that the killer thread is under way...
    if(session.getTimeout() == 0)
      throw new DLI2FEException(DLI2FEException.REQUEST_TIMEOUT_EXC, "Invalid or timed out session");
    session.extendTimeout(additionalTime);
    //dbg.println(DBG.SHORT, "Extended state timeout of " + session + " for " + timeAllotted.value);
  }

  // Private methods

  void addSession(Session s) {
    sessions.put(new Integer(s.getSID()), s);
    //dbg.println(DBG.SHORT, "New session " + s + " created");
  }

  void removeSession(Session s) {
    s.cancel();
    sessions.remove(new Integer(s.getSID()));
    //dbg.println(DBG.SHORT, "Removing session " + s + ", " + sessions.size() + " left");
  }

  Session findSession(int SID) throws DLI2FEException {
    Session s = (Session)sessions.get(new Integer(SID));
    if(s == null)
      throw new DLI2FEException(DLI2FEException.REQUEST_TIMEOUT_EXC, "Invalid or timed out session");
    return s;
  }

  public String toString() {
    return "Z3950LSP_" + host + "_" + port;
  }

  public static void main(String args[]) throws Exception {

    /* Instantiate an DLI2FE/DASL transport module
     * This also starts the server on the given port */
    /*
    if(args.length < 2) {
      System.err.println("Usage: java dli2fe.sample.Z39LSP <Z39-host>[:<Z39-port>] <port> [default subcollection]");
      System.exit(1);
      }*/
    Z39LSP lsp = new Z39LSP("melvyl.ucop.edu");
    lsp.setDefaultSubcol("CATALOG");
    //Z39LSP lsp = new Z39LSP("z3950.loc.gov:7090");
    //Z39LSP lsp = new Z39LSP("202.96.221.143");
    //lsp.setDefaultSubcol("shcl");
    //Z39LSP lsp = new Z39LSP("202.120.227.53");
    //lsp.setDefaultSubcol("cnhorizon");
    //lsp.setDefaultSubcol("VOYAGER");
    //DBG dbg = new DBG(DBG.SHORT);
    //lsp.setDBG(dbg);


    /* Initialize CORBA transport only if runtime libraries are available */
    ServerCORBATransport t2 = new ServerCORBATransport();
    t2.addLSP(lsp);
  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -