public void receive(AsyncMessage message) throws MessageReceivingException {
    if (message == null) throw new NullPointerException("message cannot be null");

    GravityInternal gravity = getGravity();

    if (udpReceiver != null) {
      if (udpReceiver.isClosed()) return;

      try {
        udpReceiver.receive(message);
      } catch (MessageReceivingException e) {
        if (e.getCause() instanceof SocketException) {
          log.debug(e, "Closing unreachable UDP channel %s", getId());
          udpReceiver.close(false);
        } else log.error(e, "Cannot access UDP channel %s", getId());
      }
      return;
    }

    receivedQueueLock.lock();
    try {
      if (receivedQueue.size() + 1 > gravity.getGravityConfig().getMaxMessagesQueuedPerChannel())
        throw new MessageReceivingException(
            message, "Could not queue message (channel's queue is full) for channel: " + this);

      log.debug(
          "Channel %s queue message %s for client %s",
          getId(), message.getMessageId(), message.getClientId());
      receivedQueue.add(message);
    } finally {
      receivedQueueLock.unlock();
    }

    if (hasAsyncHttpContext()) receiver.queue(gravity);
  }
  public Object authorize(AbstractSecurityContext context) throws Exception {
    log.debug("Authorize: %s", context);
    log.debug(
        "Is %s secured? %b",
        context.getDestination().getId(), context.getDestination().isSecured());

    startAuthorization(context);

    HttpGraniteContext graniteContext = (HttpGraniteContext) GraniteContext.getCurrentInstance();

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

    SecurityContext securityContextBefore = null;
    int securityContextHashBefore = 0;
    if (graniteContext.getRequest().getAttribute(FILTER_APPLIED) == null) {
      securityContextBefore = loadSecurityContextFromSession();
      if (securityContextBefore == null) securityContextBefore = SecurityContextHolder.getContext();
      else securityContextHashBefore = securityContextBefore.hashCode();
      SecurityContextHolder.setContext(securityContextBefore);
      authentication = securityContextBefore.getAuthentication();
    }

    if (context.getDestination().isSecured()) {
      if (!isAuthenticated(authentication)
          || authentication instanceof AnonymousAuthenticationToken) {
        log.debug("Is not authenticated!");
        throw SecurityServiceException.newNotLoggedInException("User not logged in");
      }
      if (!userCanAccessService(context, authentication)) {
        log.debug("Access denied for: %s", authentication.getName());
        throw SecurityServiceException.newAccessDeniedException("User not in required role");
      }
    }

    try {
      Object returnedObject =
          securityInterceptor != null
              ? securityInterceptor.invoke(context)
              : endAuthorization(context);

      return returnedObject;
    } catch (AccessDeniedException e) {
      throw SecurityServiceException.newAccessDeniedException(e.getMessage());
    } catch (InvocationTargetException e) {
      handleAuthorizationExceptions(e);
      throw e;
    } finally {
      if (graniteContext.getRequest().getAttribute(FILTER_APPLIED) == null) {
        // Do this only when not already filtered by Spring Security
        SecurityContext securityContextAfter = SecurityContextHolder.getContext();
        SecurityContextHolder.clearContext();
        saveSecurityContextInSession(securityContextAfter, securityContextHashBefore);
      }
    }
  }
  protected boolean userCanAccessService(
      AbstractSecurityContext context, Authentication authentication) {
    log.debug("Is authenticated as: %s", authentication.getName());

    for (String role : context.getDestination().getRoles()) {
      if (isUserInRole(authentication, role)) {
        log.debug("Allowed access to %s in role %s", authentication.getName(), role);
        return true;
      }
      log.debug("Access denied for %s not in role %s", authentication.getName(), role);
    }
    return false;
  }
  private Message handleSecurityMessage(CommandMessage message) {
    GraniteConfig config = GraniteContext.getCurrentInstance().getGraniteConfig();

    Message response = null;

    if (!config.hasSecurityService())
      log.warn(
          "Ignored security operation (no security settings in granite-config.xml): %s", message);
    else if (!config.getSecurityService().acceptsContext())
      log.info(
          "Ignored security operation (security service does not handle this kind of granite context)",
          message);
    else {
      SecurityService securityService = config.getSecurityService();
      try {
        if (message.isLoginOperation())
          securityService.login(
              message.getBody(), (String) message.getHeader(Message.CREDENTIALS_CHARSET_HEADER));
        else securityService.logout();
      } catch (Exception e) {
        if (e instanceof SecurityServiceException)
          log.debug(e, "Could not process security operation: %s", message);
        else log.error(e, "Could not process security operation: %s", message);
        response = new ErrorMessage(message, e, true);
      }
    }

    if (response == null) {
      response = new AcknowledgeMessage(message, true);
      // For SDK 2.0.1_Hotfix2.
      if (message.isSecurityOperation()) response.setBody("success");
    }

    return response;
  }
  public Principal login(Object credentials, String charset) {
    List<String> decodedCredentials = Arrays.asList(decodeBase64Credentials(credentials, charset));

    HttpGraniteContext context = (HttpGraniteContext) GraniteContext.getCurrentInstance();
    HttpServletRequest httpRequest = context.getRequest();

    String user = decodedCredentials.get(0);
    String password = decodedCredentials.get(1);
    Authentication auth = new UsernamePasswordAuthenticationToken(user, password);
    Principal principal = null;

    ApplicationContext ctx =
        WebApplicationContextUtils.getWebApplicationContext(
            httpRequest.getSession().getServletContext());
    if (ctx != null) {
      AbstractAuthenticationManager authenticationManager =
          BeanFactoryUtils.beanOfTypeIncludingAncestors(ctx, AbstractAuthenticationManager.class);
      try {
        Authentication authentication = authenticationManager.authenticate(auth);
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);
        principal = authentication;
        SecurityContextHolder.setContext(securityContext);
        saveSecurityContextInSession(securityContext, 0);

        endLogin(credentials, charset);
      } catch (AuthenticationException e) {
        handleAuthenticationExceptions(e);
      }
    }

    log.debug("User %s logged in", user);

    return principal;
  }
 @Invalidate
 public void stop() {
   log.debug("Stop OSGiServiceSimple: " + toString());
   if (servicesConfig != null) {
     servicesConfig.removeService(id);
     started = false;
   }
 }
  public void encode(ExtendedObjectOutput out, Object v)
      throws IOException, IllegalAccessException, InvocationTargetException {
    String detachedState = null;

    if (v instanceof HibernateProxy) {
      HibernateProxy proxy = (HibernateProxy) v;

      // Only write initialized flag, detachedState & id if v is an uninitialized proxy.
      if (proxy.getHibernateLazyInitializer().isUninitialized()) {

        Class<?> persistentClass = proxy.getHibernateLazyInitializer().getPersistentClass();
        if (!serializableProxyAdapters.containsKey(persistentClass)) {
          try {
            SerializableProxyAdapter proxyAdapter = new SerializableProxyAdapter(proxy);
            serializableProxyAdapters.putIfAbsent(persistentClass, proxyAdapter);
          } catch (Exception e) {
            throw new IOException("Could not create SerializableProxyAdapter for: " + proxy);
          }
        }

        Serializable id = proxy.getHibernateLazyInitializer().getIdentifier();
        log.debug("Writing uninitialized HibernateProxy %s with id %s", detachedState, id);

        out.writeBoolean(false);
        out.writeUTF(null);
        out.writeObject(id);
        return;
      }

      // Proxy is initialized, get the underlying persistent object.
      log.debug("Writing initialized HibernateProxy...");
      v = proxy.getHibernateLazyInitializer().getImplementation();
    }

    // Write initialized flag & detachedState.
    out.writeBoolean(true);
    out.writeUTF(null);

    // Write all properties in lexical order.
    List<Property> properties = out.getReflection().findSerializableProperties(v.getClass());
    for (Property property : properties) out.getAndWriteProperty(v, property);
  }
  @Validate
  public void start() {
    log.debug("Start OSGiServiceSimple: " + toString());

    if (servicesConfig.findServiceById(id) == null) {
      // Clear destinations
      destinations.clear();

      servicesConfig.addService(this);
      started = true;
    } else {
      log.error("Service \"" + id + "\" already registered");
    }
  }
  @SuppressWarnings("unchecked")
  public <C extends Channel> C getChannel(ChannelFactory<C> channelFactory, String clientId) {
    if (clientId == null) return null;

    TimeChannel<C> timeChannel = (TimeChannel<C>) channels.get(clientId);
    if (timeChannel == null) {
      // Look for existing channel id/subscriptions in distributed data (clustering).
      log.debug("Lookup channel %s in distributed data", clientId);
      try {
        DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance();
        if (gdd != null && gdd.hasChannelId(clientId)) {
          log.debug("Found channel id in distributed data: %s", clientId);
          String channelFactoryClassName = gdd.getChannelFactoryClassName(clientId);
          String clientType = gdd.getChannelClientType(clientId);
          channelFactory =
              (ChannelFactory<C>)
                  TypeUtil.newInstance(
                      channelFactoryClassName, new Class<?>[] {Gravity.class}, new Object[] {this});
          C channel = channelFactory.newChannel(clientId, clientType);
          timeChannel = new TimeChannel<C>(channel);
          if (channels.putIfAbsent(clientId, timeChannel) == null) {
            for (CommandMessage subscription : gdd.getSubscriptions(clientId)) {
              log.debug("Resubscribing channel: %s - %s", clientId, subscription);
              handleSubscribeMessage(channelFactory, subscription, false);
            }
            access(clientId);
          }
        }
      } catch (Exception e) {
        log.error(
            e, "Could not recreate channel/subscriptions from distributed data: %s", clientId);
      }
    }

    return (timeChannel != null ? timeChannel.getChannel() : null);
  }
  public boolean access(String channelId) {
    if (channelId != null) {
      TimeChannel<?> timeChannel = channels.get(channelId);
      if (timeChannel != null) {
        synchronized (timeChannel) {
          TimerTask timerTask = timeChannel.getTimerTask();
          if (timerTask != null) {
            log.debug("Canceling TimerTask: %s", timerTask);
            timerTask.cancel();
            timeChannel.setTimerTask(null);
          }

          timerTask = new ChannelTimerTask(this, channelId);
          timeChannel.setTimerTask(timerTask);

          long timeout = gravityConfig.getChannelIdleTimeoutMillis();
          log.debug("Scheduling TimerTask: %s for %s ms.", timerTask, timeout);
          channelsTimer.schedule(timerTask, timeout);
          return true;
        }
      }
    }
    return false;
  }
  private Message handlePingMessage(ChannelFactory<?> channelFactory, CommandMessage message) {

    Channel channel = createChannel(channelFactory, (String) message.getClientId());

    AsyncMessage reply = new AcknowledgeMessage(message);
    reply.setClientId(channel.getId());
    Map<String, Object> advice = new HashMap<String, Object>();
    advice.put(RECONNECT_INTERVAL_MS_KEY, Long.valueOf(gravityConfig.getReconnectIntervalMillis()));
    advice.put(RECONNECT_MAX_ATTEMPTS_KEY, Long.valueOf(gravityConfig.getReconnectMaxAttempts()));
    advice.put(ENCODE_MESSAGE_BODY_KEY, Boolean.valueOf(gravityConfig.isEncodeMessageBody()));
    reply.setBody(advice);
    reply.setDestination(message.getDestination());

    log.debug("handshake.handle: reply=%s", reply);

    return reply;
  }
  public Channel removeChannel(String channelId, boolean timeout) {
    if (channelId == null) return null;

    // Remove existing channel id/subscriptions in distributed data (clustering).
    try {
      DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance();
      if (gdd != null) {
        log.debug("Removing channel id from distributed data: %s", channelId);
        gdd.removeChannelId(channelId);
      }
    } catch (Exception e) {
      log.error(e, "Could not remove channel id from distributed data: %s", channelId);
    }

    TimeChannel<?> timeChannel = channels.get(channelId);
    Channel channel = null;
    if (timeChannel != null) {
      try {
        if (timeChannel.getTimerTask() != null) timeChannel.getTimerTask().cancel();
      } catch (Exception e) {
        // Should never happen...
      }

      channel = timeChannel.getChannel();

      try {
        for (Subscription subscription : channel.getSubscriptions()) {
          try {
            Message message = subscription.getUnsubscribeMessage();
            handleMessage(channel.getFactory(), message, true);
          } catch (Exception e) {
            log.error(
                e,
                "Error while unsubscribing channel: %s from subscription: %s",
                channel,
                subscription);
          }
        }
      } finally {
        channels.remove(channelId);
        channel.destroy(timeout);
      }
    }
    return channel;
  }
  protected List<ExtendedObjectCodec> detectExtendedObjectCodecs() {
    log.info("Auto detecting extended object codec...");

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    for (String factoryName : CODEC_EXTENSION_FACTORY_NAMES) {
      try {
        CodecExtensionFactory factory =
            (CodecExtensionFactory) classLoader.loadClass(factoryName).newInstance();
        List<ExtendedObjectCodec> extendedObjectCodecs = factory.getCodecs();
        log.info("Using %s: %s", factoryName, extendedObjectCodecs);
        return extendedObjectCodecs;
      } catch (Throwable t) {
        log.debug(t, "Could not load factory: %s", factoryName);
      }
    }

    log.info("No extended object codec detected");
    return Collections.emptyList();
  }
  private Message handleUnsubscribeMessage(
      final ChannelFactory<?> channelFactory, CommandMessage message) {
    Channel channel = getChannel(channelFactory, (String) message.getClientId());
    if (channel == null) return handleUnknownClientMessage(message);

    AsyncMessage reply = null;

    ServiceAdapter adapter = adapterFactory.getServiceAdapter(message);

    reply = (AcknowledgeMessage) adapter.manage(channel, message);

    postManage(channel);

    if (!(reply instanceof ErrorMessage)) {
      // Remove subscription message in distributed data (clustering).
      try {
        DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance();
        if (gdd != null) {
          String subscriptionId =
              (String) message.getHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER);
          log.debug(
              "Removing subscription message from channel info: %s - %s",
              channel.getId(), subscriptionId);
          gdd.removeSubcription(channel.getId(), subscriptionId);
        }
      } catch (Exception e) {
        log.error(
            e,
            "Could not remove subscription from distributed data: %s - %s",
            channel.getId(),
            message.getHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER));
      }
    }

    reply.setDestination(message.getDestination());
    reply.setClientId(channel.getId());
    reply.getHeaders().putAll(message.getHeaders());

    return reply;
  }
  protected <C extends Channel> C createChannel(ChannelFactory<C> channelFactory, String clientId) {
    C channel = null;
    if (clientId != null) {
      channel = getChannel(channelFactory, clientId);
      if (channel != null) return channel;
    }

    String clientType = GraniteContext.getCurrentInstance().getClientType();
    channel = channelFactory.newChannel(UUIDUtil.randomUUID(), clientType);
    TimeChannel<C> timeChannel = new TimeChannel<C>(channel);
    for (int i = 0; channels.putIfAbsent(channel.getId(), timeChannel) != null; i++) {
      if (i >= 10)
        throw new RuntimeException("Could not find random new clientId after 10 iterations");
      channel.destroy(false);
      channel = channelFactory.newChannel(UUIDUtil.randomUUID(), clientType);
      timeChannel = new TimeChannel<C>(channel);
    }

    String channelId = channel.getId();

    // Save channel id in distributed data (clustering).
    try {
      DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance();
      if (gdd != null) {
        log.debug("Saving channel id in distributed data: %s", channelId);
        gdd.addChannelId(channelId, channelFactory.getClass().getName(), clientType);
      }
    } catch (Exception e) {
      log.error(e, "Could not add channel id in distributed data: %s", channelId);
    }

    // Initialize timer task.
    access(channelId);

    return channel;
  }
Exemple #16
0
  public boolean runReceived(AsyncHttpContext asyncHttpContext) {

    boolean httpAsParam = (asyncHttpContext != null);
    LinkedList<AsyncMessage> messages = null;
    OutputStream os = null;

    try {
      receivedQueueLock.lock();
      try {
        // Do we have any pending messages?
        if (receivedQueue.isEmpty()) return false;

        // Do we have a valid http context?
        if (asyncHttpContext == null) {
          asyncHttpContext = acquireAsyncHttpContext();
          if (asyncHttpContext == null) return false;
        }

        // Both conditions are ok, get all pending messages.
        messages = receivedQueue;
        receivedQueue = new LinkedList<AsyncMessage>();
      } finally {
        receivedQueueLock.unlock();
      }

      HttpServletRequest request = asyncHttpContext.getRequest();
      HttpServletResponse response = asyncHttpContext.getResponse();

      // Set response messages correlation ids to connect request message id.
      String correlationId = asyncHttpContext.getConnectMessage().getMessageId();
      AsyncMessage[] messagesArray = new AsyncMessage[messages.size()];
      int i = 0;
      for (AsyncMessage message : messages) {
        message.setCorrelationId(correlationId);
        messagesArray[i++] = message;
      }

      // Setup serialization context (thread local)
      Gravity gravity = getGravity();
      GraniteContext context =
          HttpGraniteContext.createThreadIntance(
              gravity.getGraniteConfig(), gravity.getServicesConfig(), null, request, response);
      ((AMFContextImpl) context.getAMFContext())
          .setCurrentAmf3Message(asyncHttpContext.getConnectMessage());

      // Write messages to response output stream.

      response.setStatus(HttpServletResponse.SC_OK);
      response.setContentType(AMF0Message.CONTENT_TYPE);
      response.setDateHeader("Expire", 0L);
      response.setHeader("Cache-Control", "no-store");

      os = response.getOutputStream();
      ObjectOutput amf3Serializer = context.getGraniteConfig().newAMF3Serializer(os);

      log.debug("<< [MESSAGES for channel=%s] %s", this, messagesArray);

      amf3Serializer.writeObject(messagesArray);

      os.flush();
      response.flushBuffer();

      return true; // Messages were delivered, http context isn't valid anymore.
    } catch (IOException e) {
      log.warn(e, "Could not send messages to channel: %s (retrying later)", this);

      GravityConfig gravityConfig = getGravity().getGravityConfig();
      if (messages != null && gravityConfig.isRetryOnError()) {
        receivedQueueLock.lock();
        try {
          if (receivedQueue.size() + messages.size()
              > gravityConfig.getMaxMessagesQueuedPerChannel()) {
            log.warn(
                "Channel %s has reached its maximum queue capacity %s (throwing %s messages)",
                this, gravityConfig.getMaxMessagesQueuedPerChannel(), messages.size());
          } else receivedQueue.addAll(0, messages);
        } finally {
          receivedQueueLock.unlock();
        }
      }

      return true; // Messages weren't delivered, but http context isn't valid anymore.
    } finally {

      // Cleanup serialization context (thread local)
      try {
        GraniteContext.release();
      } catch (Exception e) {
        // should never happen...
      }

      // Close output stream.
      try {
        if (os != null) {
          try {
            os.close();
          } catch (IOException e) {
            log.warn(e, "Could not close output stream (ignored)");
          }
        }
      } finally {
        // Cleanup http context (only if this method wasn't explicitly called with a non null
        // AsyncHttpContext from the servlet).
        if (!httpAsParam) releaseAsyncHttpContext(asyncHttpContext);
      }
    }
  }
  /* (non-Javadoc)
   * @see org.granite.tide.ejb.EJBServiceContextIntf#findComponent(java.lang.String)
   */
  @Override
  public Object findComponent(String componentName, Class<?> componentClass) {
    if ("identity".equals(componentName)) return identity;

    EjbComponent component = ejbLookupCache.get(componentName);
    if (component != null) return component.ejbInstance;

    // Compute EJB JNDI binding.
    String name = componentName;
    if (lookup != null) {
      name = lookup;
      if (lookup.contains(CAPITALIZED_DESTINATION_ID))
        name = lookup.replace(CAPITALIZED_DESTINATION_ID, capitalize(componentName));
      if (lookup.contains(DESTINATION_ID)) name = lookup.replace(DESTINATION_ID, componentName);
    }

    InitialContext ic = null;
    try {
      ic = new InitialContext();
    } catch (Exception e) {
      throw new ServiceException("Could not get InitialContext", e);
    }

    log.debug(">> New EjbServiceInvoker looking up: %s", name);

    try {
      component = new EjbComponent();
      component.ejbInstance = ic.lookup(name);
      component.ejbClasses = new HashSet<Class<?>>();
      Class<?> scannedClass = null;
      EjbScannedItemHandler itemHandler = EjbScannedItemHandler.instance();
      for (Class<?> i : component.ejbInstance.getClass().getInterfaces()) {
        if (itemHandler.getScannedClasses().containsKey(i)) {
          scannedClass = itemHandler.getScannedClasses().get(i);
          break;
        }
      }
      if (scannedClass == null)
        scannedClass = itemHandler.getScannedClasses().get(component.ejbInstance.getClass());
      // GDS-768: handle of proxied no-interface EJBs in GlassFish v3
      if (scannedClass == null && component.ejbInstance.getClass().getSuperclass() != null)
        scannedClass =
            itemHandler.getScannedClasses().get(component.ejbInstance.getClass().getSuperclass());

      if (scannedClass != null) {
        component.ejbClasses.add(scannedClass);
        for (Map.Entry<Class<?>, Class<?>> me : itemHandler.getScannedClasses().entrySet()) {
          if (me.getValue().equals(scannedClass)) component.ejbClasses.add(me.getKey());
        }
        component.ejbMetadata =
            new EjbServiceMetadata(scannedClass, component.ejbInstance.getClass());
      } else
        log.warn(
            "Ejb "
                + componentName
                + " was not scanned: remove method will not be called if it is a Stateful bean. Add META-INF/services-config.properties if needed.");

      ejbLookupCache.put(componentName, component);

      return component.ejbInstance;
    } catch (NamingException e) {
      log.error("EJB not found " + name + ": " + e.getMessage());
      throw new ServiceException("Could not lookup for: " + name, e);
    }
  }
 @Override
 protected void beforeInvocation(ServiceInvocationContext context) {
   log.debug("Before Invocation");
 }
 @Override
 protected Object afterInvocation(ServiceInvocationContext context, Object result) {
   log.debug("After Invocation");
   return result;
 }
 public SpringSecurityService() {
   log.debug("Starting Spring Security Service!");
 }
 public void configure(Map<String, String> params) {
   log.debug("Configuring with parameters (NOOP) %s: ", params);
 }